├── 9781430246596.jpg
├── Ch04
├── cab.test
└── source_Ch04.zip
├── Ch06
├── BookVendingMachine
│ ├── AdminForm.h
│ ├── AdminForm.resx
│ ├── AssemblyInfo.cpp
│ ├── BookVendingMachine.cpp
│ ├── BookVendingMachine.vcxproj
│ ├── DBEngine.cpp
│ ├── DBEngine.h
│ ├── MainForm.h
│ ├── MainForm.resx
│ ├── app.aps
│ └── resource.h
├── example1_win32
│ ├── example1_win32.cpp
│ └── example1_win32.vcxproj
└── source_ch06.zip
├── Ch07
├── diskusage.diff
├── diskusage_is.diff
├── gregorian.diff
├── julian.diff
└── source_Ch07.zip
├── Ch08
├── slave_connect_log_event.diff
├── source_Ch08.zip
└── stop_slaves.diff
├── Ch09
├── rfid_auth
│ ├── CMakeLists.txt
│ ├── rfid_auth.cc
│ └── rfid_auth.ini
└── source_Ch09.zip
├── Ch10
├── ch10_results.txt
├── source_Ch10.zip
├── stage_five
│ ├── CMakeLists.txt
│ ├── Ch10s5.test
│ ├── ha_spartan.cc
│ ├── ha_spartan.h
│ ├── spartan_data.cc
│ ├── spartan_data.h
│ ├── spartan_index.cc
│ └── spartan_index.h
├── stage_four
│ ├── CMakeLists.txt
│ ├── Ch10s4.test
│ ├── ha_spartan.cc
│ ├── ha_spartan.h
│ ├── spartan_data.cc
│ └── spartan_data.h
├── stage_one
│ ├── CMakeLists.txt
│ ├── Ch10s1.test
│ ├── ha_spartan.cc
│ ├── ha_spartan.h
│ ├── spartan_data.cc
│ └── spartan_data.h
├── stage_three
│ ├── CMakeLists.txt
│ ├── Ch10s3.test
│ ├── ha_spartan.cc
│ ├── ha_spartan.h
│ ├── spartan_data.cc
│ └── spartan_data.h
└── stage_two
│ ├── CMakeLists.txt
│ ├── Ch10s2.test
│ ├── ha_spartan.cc
│ ├── ha_spartan.h
│ ├── spartan_data.cc
│ └── spartan_data.h
├── Ch12
├── ch12.diff
├── ch12.sql
├── ch12.test
├── query_tree.cc
├── query_tree.h
├── source_Ch12.zip
└── sql_dbxp_parse.cc
├── Ch13
├── attribute.cc
├── attribute.h
├── ch13.diff
├── ch13.result
├── ch13.test
├── ch13.txt
├── ch13_results.txt
├── expression.cc
├── expression.h
├── query_tree.cc
├── query_tree.h
├── source_Ch13.zip
└── sql_dbxp_parse.cc
├── Ch14
├── attribute.cc
├── attribute.h
├── ch14.diff
├── ch14.result
├── ch14.test
├── ch14.txt
├── expression.cc
├── expression.h
├── query_tree.cc
├── query_tree.h
├── source_Ch14.zip
└── sql_dbxp_parse.cc
├── LICENSE.txt
├── README.md
├── Sample_data
├── bvm_data.sql
├── bvm_images.zip
└── sample_data.sql
└── contributing.md
/9781430246596.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/9781430246596.jpg
--------------------------------------------------------------------------------
/Ch04/cab.test:
--------------------------------------------------------------------------------
1 | #
2 | # Sample test to demonstrate MySQL Test Suite
3 | #
4 | --disable_warnings
5 | SHOW DATABASES;
6 | --enable_warnings
7 | CREATE TABLE characters (ID INTEGER PRIMARY KEY,
8 | LastName varchar(40),
9 | FirstName varchar(20),
10 | Gender varchar(2)) ENGINE=MYISAM;
11 | EXPLAIN characters;
12 | #
13 | INSERT INTO characters (ID, LastName, FirstName, Gender)
14 | VALUES (3, 'Flintstone', 'Fred', 'M');
15 | INSERT INTO characters (ID, LastName, FirstName, Gender)
16 | VALUES (5, 'Rubble', 'Barney', 'M');
17 | INSERT INTO characters (ID, LastName, FirstName, Gender)
18 | VALUES (7, 'Flintstone', 'Wilma', 'F');
19 | INSERT INTO characters (ID, LastName, FirstName, Gender)
20 | VALUES (9, 'Flintstone', 'Dino', 'M');
21 | INSERT INTO characters (ID, LastName, FirstName, Gender)
22 | VALUES (4, 'Flintstone', 'Pebbles', 'F');
23 | INSERT INTO characters (ID, LastName, FirstName, Gender)
24 | VALUES (1, 'Rubble', 'Betty', 'F');
25 | INSERT INTO characters (ID, LastName, FirstName, Gender)
26 | VALUES (6, 'Rubble', 'Bam-Bam', 'M');
27 | INSERT INTO characters (ID, LastName, FirstName, Gender)
28 | VALUES (8, 'Jetson', 'George', 'M');
29 | #
30 | SELECT * FROM characters;
31 | #
32 | EXPLAIN (SELECT DISTINCT LASTNAME from characters);
33 | #
34 | SELECT DISTINCT LASTNAME from characters;
35 | #
36 | # Cleanup
37 | #
38 | DROP TABLE characters;
39 |
--------------------------------------------------------------------------------
/Ch04/source_Ch04.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch04/source_Ch04.zip
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/AdminForm.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include "DBEngine.h"
3 |
4 | using namespace System;
5 | using namespace System::ComponentModel;
6 | using namespace System::Collections;
7 | using namespace System::Windows::Forms;
8 | using namespace System::Data;
9 | using namespace System::Drawing;
10 |
11 |
12 | namespace BookVendingMachine {
13 |
14 | DBEngine *AdminDatabase = new DBEngine();
15 |
16 | ///
17 | /// Summary for Admin
18 | ///
19 | /// WARNING: If you change the name of this class, you will need to change the
20 | /// 'Resource File Name' property for the managed resource compiler tool
21 | /// associated with all .resx files this class depends on. Otherwise,
22 | /// the designers will not be able to interact properly with localized
23 | /// resources associated with this form.
24 | ///
25 |
26 | public ref class AdminForm: public System::Windows::Forms::Form
27 | {
28 | public:
29 | AdminForm(void)
30 | {
31 | InitializeComponent();
32 | //
33 | //TODO: Add the constructor code here
34 | //
35 | }
36 |
37 | protected:
38 | ///
39 | /// Clean up any resources being used.
40 | ///
41 | ~AdminForm()
42 | {
43 | if (components)
44 | {
45 | delete components;
46 | }
47 | }
48 |
49 | protected:
50 | private: System::Windows::Forms::TextBox^ txtQuery;
51 | private: System::Windows::Forms::Button^ btnExecute;
52 | private: System::Windows::Forms::ListBox^ lstData;
53 | private: System::Windows::Forms::Label^ label1;
54 |
55 | private:
56 | ///
57 | /// Required designer variable.
58 | ///
59 | System::ComponentModel::Container ^components;
60 |
61 | #pragma region Windows Form Designer generated code
62 | ///
63 | /// Required method for Designer support - do not modify
64 | /// the contents of this method with the code editor.
65 | ///
66 | void InitializeComponent(void)
67 | {
68 | this->txtQuery = (gcnew System::Windows::Forms::TextBox());
69 | this->btnExecute = (gcnew System::Windows::Forms::Button());
70 | this->lstData = (gcnew System::Windows::Forms::ListBox());
71 | this->label1 = (gcnew System::Windows::Forms::Label());
72 | this->SuspendLayout();
73 | //
74 | // txtQuery
75 | //
76 | this->txtQuery->Anchor = static_cast(((System::Windows::Forms::AnchorStyles::Bottom | System::Windows::Forms::AnchorStyles::Left)
77 | | System::Windows::Forms::AnchorStyles::Right));
78 | this->txtQuery->Font = (gcnew System::Drawing::Font(L"Courier New", 9.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
79 | static_cast(0)));
80 | this->txtQuery->Location = System::Drawing::Point(12, 219);
81 | this->txtQuery->Multiline = true;
82 | this->txtQuery->Name = L"txtQuery";
83 | this->txtQuery->Size = System::Drawing::Size(721, 53);
84 | this->txtQuery->TabIndex = 2;
85 | //
86 | // btnExecute
87 | //
88 | this->btnExecute->Anchor = static_cast((System::Windows::Forms::AnchorStyles::Bottom | System::Windows::Forms::AnchorStyles::Right));
89 | this->btnExecute->Location = System::Drawing::Point(658, 278);
90 | this->btnExecute->Name = L"btnExecute";
91 | this->btnExecute->Size = System::Drawing::Size(75, 23);
92 | this->btnExecute->TabIndex = 3;
93 | this->btnExecute->Text = L"Execute";
94 | this->btnExecute->UseVisualStyleBackColor = true;
95 | this->btnExecute->Click += gcnew System::EventHandler(this, &AdminForm::btnExecute_Click);
96 | //
97 | // lstData
98 | //
99 | this->lstData->Anchor = static_cast((((System::Windows::Forms::AnchorStyles::Top | System::Windows::Forms::AnchorStyles::Bottom)
100 | | System::Windows::Forms::AnchorStyles::Left)
101 | | System::Windows::Forms::AnchorStyles::Right));
102 | this->lstData->Font = (gcnew System::Drawing::Font(L"Courier New", 9.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
103 | static_cast(0)));
104 | this->lstData->FormattingEnabled = true;
105 | this->lstData->HorizontalScrollbar = true;
106 | this->lstData->ItemHeight = 16;
107 | this->lstData->Location = System::Drawing::Point(12, 28);
108 | this->lstData->MultiColumn = true;
109 | this->lstData->Name = L"lstData";
110 | this->lstData->Size = System::Drawing::Size(721, 180);
111 | this->lstData->TabIndex = 4;
112 | //
113 | // label1
114 | //
115 | this->label1->AutoSize = true;
116 | this->label1->Font = (gcnew System::Drawing::Font(L"Courier New", 9.75F, System::Drawing::FontStyle::Regular, System::Drawing::GraphicsUnit::Point,
117 | static_cast(0)));
118 | this->label1->Location = System::Drawing::Point(12, 9);
119 | this->label1->Name = L"label1";
120 | this->label1->Size = System::Drawing::Size(688, 16);
121 | this->label1->TabIndex = 5;
122 | this->label1->Text = L"(ISBN, Slot, Quantity, Price, Pages, PubDate, Title, Authors, Thumbnail, Descript"
123 | L"ion)";
124 | //
125 | // AdminForm
126 | //
127 | this->AutoScaleDimensions = System::Drawing::SizeF(6, 13);
128 | this->AutoScaleMode = System::Windows::Forms::AutoScaleMode::Font;
129 | this->ClientSize = System::Drawing::Size(745, 311);
130 | this->Controls->Add(this->label1);
131 | this->Controls->Add(this->lstData);
132 | this->Controls->Add(this->btnExecute);
133 | this->Controls->Add(this->txtQuery);
134 | this->Name = L"AdminForm";
135 | this->Text = L"Book Vending Machine Administration";
136 | this->FormClosing += gcnew System::Windows::Forms::FormClosingEventHandler(this, &AdminForm::AdminForm_FormClosing);
137 | this->Load += gcnew System::EventHandler(this, &AdminForm::Admin_Load);
138 | this->ResumeLayout(false);
139 | this->PerformLayout();
140 |
141 | }
142 | #pragma endregion
143 | void LoadList()
144 | {
145 | int i = 0;
146 | int j = 0;
147 | String^ str;
148 |
149 | lstData->Items->Clear();
150 | AdminDatabase->StartQuery("SELECT ISBN, Slot, Quantity, Price," \
151 | " Pages, PubDate, Title, Authors, Thumbnail," \
152 | " Description FROM books");
153 | do
154 | {
155 | str = gcnew String("");
156 | for (i = 0; i < 10; i++)
157 | {
158 | if (i != 0)
159 | {
160 | str = str + "\t";
161 | }
162 | str = str + gcnew String(AdminDatabase->GetField(i));
163 | }
164 | lstData->Items->Add(str);
165 | j++;
166 | }while(AdminDatabase->GetNext());
167 | }
168 |
169 | private: System::Void btnExecute_Click(System::Object^ sender, System::EventArgs^ e)
170 | {
171 | String ^orig = gcnew String(txtQuery->Text->ToString());
172 | pin_ptr wch = PtrToStringChars(orig);
173 |
174 | // Convert to a char*
175 | size_t origsize = wcslen(wch) + 1;
176 | const size_t newsize = 100;
177 | size_t convertedChars = 0;
178 | char nstring[newsize];
179 | wcstombs_s(&convertedChars, nstring, origsize, wch, _TRUNCATE);
180 | AdminDatabase->RunQuery(nstring);
181 | LoadList();
182 | }
183 |
184 | private: System::Void Admin_Load(System::Object^ sender, System::EventArgs^ e)
185 | {
186 | AdminDatabase->Initialize();
187 | LoadList();
188 | }
189 |
190 | private: System::Void AdminForm_FormClosing(System::Object^ sender, System::Windows::Forms::FormClosingEventArgs^ e)
191 | {
192 | AdminDatabase->Shutdown();
193 | }
194 | };
195 | }
196 |
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/AdminForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/AssemblyInfo.cpp:
--------------------------------------------------------------------------------
1 | using namespace System;
2 | using namespace System::Reflection;
3 | using namespace System::Runtime::CompilerServices;
4 | using namespace System::Runtime::InteropServices;
5 | using namespace System::Security::Permissions;
6 |
7 | //
8 | // General Information about an assembly is controlled through the following
9 | // set of attributes. Change these attribute values to modify the information
10 | // associated with an assembly.
11 | //
12 | [assembly:AssemblyTitleAttribute("BookVendingMachine")];
13 | [assembly:AssemblyDescriptionAttribute("")];
14 | [assembly:AssemblyConfigurationAttribute("")];
15 | [assembly:AssemblyCompanyAttribute("")];
16 | [assembly:AssemblyProductAttribute("BookVendingMachine")];
17 | [assembly:AssemblyCopyrightAttribute("Copyright (c) 2006")];
18 | [assembly:AssemblyTrademarkAttribute("")];
19 | [assembly:AssemblyCultureAttribute("")];
20 |
21 | //
22 | // Version information for an assembly consists of the following four values:
23 | //
24 | // Major Version
25 | // Minor Version
26 | // Build Number
27 | // Revision
28 | //
29 | // You can specify all the value or you can default the Revision and Build Numbers
30 | // by using the '*' as shown below:
31 |
32 | [assembly:AssemblyVersionAttribute("1.0.*")];
33 |
34 | [assembly:ComVisible(false)];
35 |
36 | [assembly:CLSCompliantAttribute(true)];
37 |
38 | [assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
39 |
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/BookVendingMachine.cpp:
--------------------------------------------------------------------------------
1 | // BookVendingMachine.cpp : main project file.
2 |
3 | #include "MainForm.h"
4 | #include "AdminForm.h"
5 |
6 | using namespace BookVendingMachine;
7 |
8 | [STAThreadAttribute]
9 | int main(array ^args)
10 | {
11 | // Enabling Windows XP visual effects before any controls are created
12 | Application::EnableVisualStyles();
13 | Application::SetCompatibleTextRenderingDefault(false);
14 |
15 | // Create the main window and run it
16 | if ((args->Length == 1) && (args[0] == "-admin"))
17 | {
18 | Application::Run(gcnew AdminForm());
19 | }
20 | else
21 | {
22 | Application::Run(gcnew MainForm());
23 | }
24 | return 0;
25 | }
26 |
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/BookVendingMachine.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 | Template
14 | Win32
15 |
16 |
17 |
18 | {99EA9ED6-10E3-458D-8D20-7F38D014397C}
19 | BookVendingMachine
20 | ManagedCProj
21 |
22 |
23 |
24 | Application
25 | Unicode
26 | Pure
27 | true
28 |
29 |
30 | Application
31 | Unicode
32 | true
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | <_ProjectFileVersion>10.0.30319.1
46 | Debug\
47 | $(Configuration)\
48 | true
49 | $(SolutionDir)$(Configuration)\
50 | $(Configuration)\
51 | false
52 |
53 |
54 |
55 | /I ../include %(AdditionalOptions)
56 | Disabled
57 | WIN32;_DEBUG;%(PreprocessorDefinitions)
58 | MultiThreadedDebugDLL
59 |
60 |
61 | Level3
62 | ProgramDatabase
63 |
64 |
65 |
66 |
67 | true
68 | true
69 | Windows
70 | main
71 | MachineX86
72 |
73 |
74 |
75 |
76 | WIN32;NDEBUG;%(PreprocessorDefinitions)
77 | MultiThreadedDLL
78 | Use
79 | Level3
80 | ProgramDatabase
81 |
82 |
83 |
84 |
85 | true
86 | Windows
87 | main
88 | MachineX86
89 |
90 |
91 |
92 |
93 | true
94 | true
95 |
96 |
97 | true
98 | true
99 |
100 |
101 | true
102 | true
103 |
104 |
105 | true
106 | true
107 |
108 |
109 | true
110 | true
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 | CppForm
121 |
122 |
123 |
124 | CppForm
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 | AdminForm.h
134 | Designer
135 |
136 |
137 | MainForm.h
138 | Designer
139 |
140 |
141 |
142 |
143 | {e373b9a3-a3df-40d4-af21-747e8fede36c}
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/DBEngine.cpp:
--------------------------------------------------------------------------------
1 | #pragma unmanaged
2 |
3 | #include "DBEngine.h"
4 | #include
5 | #include
6 | #include "my_global.h"
7 | #include "mysql.h"
8 |
9 | MYSQL *mysql; //the embedded server class
10 | MYSQL_RES *results; //stores results from queries
11 | MYSQL_ROW record; //a single row in a result set
12 | bool IteratorStarted; //used to control iterator
13 | MYSQL_RES *ExecQuery(char *Query);
14 |
15 | /*
16 | These variables set the location of the ini file and data stores.
17 | */
18 | static char *server_options[] = {"mysql_test",
19 | "--defaults-file=c:\\mysql_embedded\\my.ini",
20 | "--datadir=c:\\mysql_embedded\\data" };
21 | int num_elements=sizeof(server_options) / sizeof(char *);
22 | static char *server_groups[] = {"libmyswld_server", "libmysqld_client" };
23 |
24 | DBEngine::DBEngine(void)
25 | {
26 | mysqlError = false;
27 | }
28 |
29 | DBEngine::~DBEngine(void)
30 | {
31 | }
32 |
33 | const char *DBEngine::GetError()
34 | {
35 | return (mysql_error(mysql));
36 | mysqlError = false;
37 | }
38 |
39 | bool DBEngine::Error()
40 | {
41 | return(mysqlError);
42 | }
43 |
44 | char *DBEngine::GetBookFieldStr(int Slot, char *Field)
45 | {
46 | char *istr = new char[10];
47 | char *str = new char[128];
48 |
49 | _itoa_s(Slot, istr, 10, 10);
50 | strcpy_s(str, 128, "SELECT ");
51 | strcat_s(str, 128, Field);
52 | strcat_s(str, 128, " FROM books WHERE Slot = ");
53 | strcat_s(str, 128, istr);
54 | mysqlError = false;
55 | results=ExecQuery(str);
56 | strcpy_s(str, 128, "");
57 | if (results)
58 | {
59 | mysqlError = false;
60 | record=mysql_fetch_row(results);
61 | if(record)
62 | {
63 | strcpy_s(str, 128, record[0]);
64 | }
65 | else
66 | {
67 | mysqlError = true;
68 | }
69 | }
70 | return (str);
71 | }
72 |
73 | char *DBEngine::GetBookFieldText(int Slot, char *Field)
74 | {
75 | char *istr = new char[10];
76 | char *str = new char[128];
77 |
78 | _itoa_s(Slot, istr, 10, 10);
79 | strcpy_s(str, 128, "SELECT ");
80 | strcat_s(str, 128, Field);
81 | strcat_s(str, 128, " FROM books WHERE Slot = ");
82 | strcat_s(str, 128, istr);
83 | mysqlError = false;
84 | results=ExecQuery(str);
85 | delete str;
86 | if (results)
87 | {
88 | mysqlError = false;
89 | record=mysql_fetch_row(results);
90 | if(record)
91 | {
92 | return (record[0]);
93 | }
94 | else
95 | {
96 | mysqlError = true;
97 | }
98 | }
99 | return ("");
100 | }
101 |
102 | int DBEngine::GetBookFieldInt(int Slot, char *Field)
103 | {
104 | char *istr = new char[10];
105 | char *str = new char[128];
106 | int qty = 0;
107 |
108 | _itoa_s(Slot, istr, 10, 10);
109 | strcpy_s(str, 128, "SELECT ");
110 | strcat_s(str, 128, Field);
111 | strcat_s(str, 128, " FROM books WHERE Slot = ");
112 | strcat_s(str, 128, istr);
113 | results=ExecQuery(str);
114 | if (results)
115 | {
116 | record=mysql_fetch_row(results);
117 | if(record)
118 | {
119 | qty = atoi(record[0]);
120 | }
121 | else
122 | {
123 | mysqlError = true;
124 | }
125 | }
126 | delete str;
127 | return (qty);
128 | }
129 |
130 | void DBEngine::VendBook(char *ISBN)
131 | {
132 | char *str = new char[128];
133 | char *istr = new char[10];
134 | int qty = 0;
135 |
136 | strcpy_s(str, 128, "SELECT Quantity FROM books WHERE ISBN = '");
137 | strcat_s(str, 128, ISBN);
138 | strcat_s(str, 128, "'");
139 | results=ExecQuery(str);
140 | record=mysql_fetch_row(results);
141 | if (record)
142 | {
143 | qty = atoi(record[0]);
144 | if (qty >= 1)
145 | {
146 | _itoa_s(qty - 1, istr, 10, 10);
147 | strcpy_s(str, 128, "UPDATE books SET Quantity = ");
148 | strcat_s(str, 128, istr);
149 | strcat_s(str, 128, " WHERE ISBN = '");
150 | strcat_s(str, 128, ISBN);
151 | strcat_s(str, 128, "'");
152 | results=ExecQuery(str);
153 | }
154 | }
155 | else
156 | {
157 | mysqlError = true;
158 | }
159 | }
160 |
161 | void DBEngine::Initialize()
162 | {
163 | /*
164 | This section initializes the server and sets server options.
165 | */
166 | mysql_server_init(num_elements, server_options, server_groups);
167 | mysql = mysql_init(NULL);
168 | if (mysql)
169 | {
170 | mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client");
171 | mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
172 | /*
173 | The following call turns debugging on programmatically.
174 | Comment out to turn on debugging.
175 | */
176 | //mysql_debug("d:t:i:O,\\mysqld_embedded.trace");
177 | /*
178 | Connect to embedded server.
179 | */
180 | if(mysql_real_connect(mysql, NULL, NULL, NULL, "mysql", 0, NULL, 0) == NULL)
181 | {
182 | mysqlError = true;
183 | }
184 | else
185 | {
186 | mysql_query(mysql, "use BVM;");
187 | }
188 | }
189 | else
190 | {
191 | mysqlError = true;
192 | }
193 | IteratorStarted = false;
194 | }
195 |
196 | void DBEngine::Shutdown()
197 | {
198 | /*
199 | Now close the server connection and tell server we're done (shutdown).
200 | */
201 | mysql_close(mysql);
202 | mysql_server_end();
203 | }
204 |
205 | char *DBEngine::GetSetting(char *Field)
206 | {
207 | char *str = new char[128];
208 | strcpy_s(str, 128, "SELECT * FROM settings WHERE FieldName = '");
209 | strcat_s(str, 128, Field);
210 | strcat_s(str, 128, "'");
211 | results=ExecQuery(str);
212 | strcpy_s(str, 128, "");
213 | if (results)
214 | {
215 | record=mysql_fetch_row(results);
216 | if (record)
217 | {
218 | strcpy_s(str, 128, record[1]);
219 | }
220 | }
221 | else
222 | {
223 | mysqlError = true;
224 | }
225 | return (str);
226 | }
227 |
228 | void DBEngine::StartQuery(char *QueryStatement)
229 | {
230 | if (!IteratorStarted)
231 | {
232 | results=ExecQuery(QueryStatement);
233 | if (results)
234 | {
235 | record=mysql_fetch_row(results);
236 | }
237 | }
238 | IteratorStarted=true;
239 | }
240 |
241 | void DBEngine::RunQuery(char *QueryStatement)
242 | {
243 | results=ExecQuery(QueryStatement);
244 | if (results)
245 | {
246 | record=mysql_fetch_row(results);
247 | if(!record)
248 | {
249 | mysqlError = true;
250 | }
251 | }
252 | }
253 |
254 | int DBEngine::GetNext()
255 | {
256 | //if EOF then no more records
257 | IteratorStarted=false;
258 | record=mysql_fetch_row(results);
259 | if (record)
260 | {
261 | return (1);
262 | }
263 | else
264 | {
265 | return (0);
266 | }
267 | }
268 |
269 | char *DBEngine::GetField(int fldNum)
270 | {
271 | if (record)
272 | {
273 | return (record[fldNum]);
274 | }
275 | else
276 | {
277 | return ("");
278 | }
279 | }
280 |
281 | MYSQL_RES *ExecQuery(char *Query)
282 | {
283 | mysql_dbug_print("ExecQuery.");
284 | mysql_free_result(results);
285 | mysql_query(mysql, Query);
286 | return (mysql_store_result(mysql));
287 | }
288 | #pragma managed
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/DBEngine.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #pragma unmanaged
3 | #include
4 |
5 | class DBEngine
6 | {
7 | private:
8 | bool mysqlError;
9 | public:
10 | DBEngine(void);
11 | const char *GetError();
12 | bool Error();
13 | void Initialize();
14 | void Shutdown();
15 | char *GetSetting(char *Field);
16 | char *GetBookFieldStr(int Slot, char *Field);
17 | char *GetBookFieldText(int Slot, char *Field);
18 | int GetBookFieldInt(int Slot, char *Field);
19 | int GetQty(int Slot);
20 | void VendBook(char *ISBN);
21 | void StartQuery(char *QueryStatement);
22 | void RunQuery(char *QueryStatement);
23 | int GetNext();
24 | char *GetField(int fldNum);
25 | ~DBEngine(void);
26 | };
27 | #pragma managed
28 |
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/MainForm.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | True
122 |
123 |
124 |
125 |
126 | AAABAAIAICAQAAAAAADoAgAAJgAAABAQEAAAAAAAKAEAAA4DAAAoAAAAIAAAAEAAAAABAAQAAAAAAIAC
127 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAAAACAAIAAgIAAAICAgADAwMAAAAD/AAD/
128 | AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
129 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
130 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACIAAAAAAAAAAAAAAAAAACQd4gAAA
131 | AAAAAAAAAAAAAJkHd3iAAAAAAAAAAAAAAAmZgAd3eIAAAAAAAAAAAACZmAmQB3d4gAAAAAAAAAAJmYCZ
132 | mZAHd3AAAAAAAAAAmZgJmZmZkAdwAAAAAAAACZmAmZmZmZmQAAAAAAAAAJmYCZmZmZmZmZAAAAAAAAmZ
133 | gJmZmZmZmZmQAAAAAAAJmAmZmZmZmZmZAAAAAAAACYCZmZmZmZmZkAAAAAAAAAgJmZmZmZmZmQAAAAAA
134 | AAAACZmZmZmZmZAAAAAAAAAAAAAJmZmZmZkAAAAAAAAAAAAAAAmZmZmQAAAAAAAAAAAAAAAACZmZAAAA
135 | AAAAAAAAAAAAAAAJkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
136 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////
137 | ////////////////////////////////x////4H///8Af//+AB///AAH//gAAf/wAAP/4AAD/8AAA/+A
138 | AAH/AAAD/wAAB/8AAA//AAAf/4AAP//gAH//+AD///4B////g////+f/////////////////////////
139 | //8oAAAAEAAAACAAAAABAAQAAAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAgAAAAICAAIAA
140 | AACAAIAAgIAAAICAgADAwMAAAAD/AAD/AAAA//8A/wAAAP8A/wD//wAA////AAAAAAAAAAAAAAAAAAAA
141 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkHAAAAAAAAmAeIAAAAAAmAAHeAAAAAmAmZAHAAAAmAmZmZAAAA
142 | CAmZmZkAAAAAmZmZkAAAAAAJmZkAAAAAAAAJkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//8AAP//
143 | AAD//wAA/48AAP8DAAD+AAAA/AEAAPgBAADwAAAA8AEAAPADAAD4BwAA/g8AAP+fAAD//wAA//8AAA==
144 |
145 |
146 |
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/app.aps:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch06/BookVendingMachine/app.aps
--------------------------------------------------------------------------------
/Ch06/BookVendingMachine/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by app.rc
4 |
--------------------------------------------------------------------------------
/Ch06/example1_win32/example1_win32.cpp:
--------------------------------------------------------------------------------
1 | #include "my_global.h"
2 | #include "mysql.h"
3 |
4 | MYSQL *mysql; //the embedded server class
5 | MYSQL_RES *results; //stores results from queries
6 | MYSQL_ROW record; //a single row in a result set
7 |
8 | /*
9 | These variables set the location of the ini file and data stores.
10 | */
11 | static char *server_options[] = {"mysql_test",
12 | "--defaults-file=c:\\mysql_embedded\\my.ini",
13 | "--datadir=c:\\mysql_embedded\\data" };
14 | int num_elements=sizeof(server_options) / sizeof(char *);
15 | static char *server_groups[] = {"libmysqld_server", "libmysqld_client" };
16 |
17 | int main(void)
18 | {
19 | /*
20 | This section initializes the server and sets server options.
21 | */
22 | mysql_server_init(num_elements, server_options, server_groups);
23 | mysql = mysql_init(NULL);
24 | mysql_options(mysql, MYSQL_READ_DEFAULT_GROUP, "libmysqld_client");
25 | mysql_options(mysql, MYSQL_OPT_USE_EMBEDDED_CONNECTION, NULL);
26 | /*
27 | The following call turns debugging on programmatically.
28 | Comment out to turn on debugging.
29 | */
30 | //mysql_debug("d:t:i:O,\\mysqld_embedded.trace");
31 | /*
32 | Connect to embedded server.
33 | */
34 | mysql_real_connect(mysql, NULL, NULL, NULL, "mysql", 0, NULL, 0);
35 | /*
36 | This sections executes the following commands and demonstrates
37 | how to retrieve results from a query.
38 |
39 | SHOW DATABASES;
40 | CREATE DATABASE testdb1;
41 | SHOW DATABASES;
42 | DROP DATABASE testdb1;
43 | */
44 | mysql_dbug_print("Showing databases."); //record trace
45 | mysql_query(mysql, "SHOW DATABASES;"); //issue query
46 | results = mysql_store_result(mysql); //get results
47 | printf("The following are the databases supported:\n");
48 | while(record=mysql_fetch_row(results)) //fetch row
49 | {
50 | printf("%s\n", record[0]); //process row
51 | }
52 | mysql_dbug_print("Creating the database testdb1."); //record trace
53 | mysql_query(mysql, "CREATE DATABASE testdb1;");
54 | mysql_dbug_print("Showing databases.");
55 | mysql_query(mysql, "SHOW DATABASES;"); //issue query
56 | results = mysql_store_result(mysql); //get results
57 | printf("The following are the databases supported:\n");
58 | while(record=mysql_fetch_row(results)) //fetch row
59 | {
60 | printf("%s\n", record[0]); //process row
61 | }
62 | mysql_free_result(results);
63 | mysql_dbug_print("Dropping database testdb1."); //record trace
64 | mysql_query(mysql, "DROP DATABASE testdb1;"); //issue query
65 | /*
66 | Now close the server connection and tell server we're done (shutdown).
67 | */
68 | mysql_close(mysql);
69 | mysql_server_end();
70 |
71 | return 0;
72 | }
73 |
74 |
--------------------------------------------------------------------------------
/Ch06/example1_win32/example1_win32.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Release
10 | Win32
11 |
12 |
13 |
14 | {B9BF96BD-BD73-4A9E-96E4-6AEA34499C30}
15 | example1_win32
16 | Win32Proj
17 |
18 |
19 |
20 | Application
21 | Unicode
22 | true
23 |
24 |
25 | Application
26 | Unicode
27 | false
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 | <_ProjectFileVersion>10.0.30319.1
41 | Debug\
42 | $(Configuration)\
43 | true
44 | $(SolutionDir)$(Configuration)\
45 | $(Configuration)\
46 | false
47 |
48 |
49 |
50 | /I ../include %(AdditionalOptions)
51 | Disabled
52 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
53 | false
54 | Default
55 | MultiThreadedDebugDLL
56 | NotUsing
57 | Level3
58 | ProgramDatabase
59 | CompileAsCpp
60 |
61 |
62 | true
63 | true
64 | Console
65 | MachineX86
66 | %(AdditionalDependencies)
67 |
68 |
69 |
70 |
71 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)
72 | MultiThreadedDLL
73 |
74 |
75 | Level3
76 | ProgramDatabase
77 |
78 |
79 | true
80 | Console
81 | true
82 | true
83 | MachineX86
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | {e373b9a3-a3df-40d4-af21-747e8fede36c}
95 |
96 |
97 |
98 |
99 |
100 |
--------------------------------------------------------------------------------
/Ch06/source_ch06.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch06/source_ch06.zip
--------------------------------------------------------------------------------
/Ch07/diskusage.diff:
--------------------------------------------------------------------------------
1 | === modified file 'sql/lex.h'
2 | --- sql/lex.h 2012-05-03 08:35:47 +0000
3 | +++ sql/lex.h 2012-08-14 16:09:27 +0000
4 | @@ -181,6 +181,11 @@ static SYMBOL symbols[] = {
5 | { "DISABLE", SYM(DISABLE_SYM)},
6 | { "DISCARD", SYM(DISCARD)},
7 | { "DISK", SYM(DISK_SYM)},
8 | +/* BEGIN CAB MODIFICATION */
9 | +/* Reason for Modification: */
10 | +/* Add disk usage symbol */
11 | + { "DISK_USAGE", SYM(DISK_USAGE_SYM)},
12 | +/* END CAB MODIFICATION */
13 | { "DISTINCT", SYM(DISTINCT)},
14 | { "DISTINCTROW", SYM(DISTINCT)}, /* Access likes this */
15 | { "DIV", SYM(DIV_SYM)},
16 |
17 | === modified file 'sql/sql_cmd.h'
18 | --- sql/sql_cmd.h 2012-05-28 09:09:33 +0000
19 | +++ sql/sql_cmd.h 2012-08-14 16:09:27 +0000
20 | @@ -62,7 +62,11 @@ enum enum_sql_command {
21 | SQLCOM_SHOW_SLAVE_HOSTS, SQLCOM_DELETE_MULTI, SQLCOM_UPDATE_MULTI,
22 | SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_DO,
23 | SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
24 | - SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
25 | +/* BEGIN CAB MODIFICATION */
26 | +/* Reason for Modification: */
27 | +/* Add SQLCOM_SHOW_DISK_USAGE reference */
28 | + SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES, SQLCOM_SHOW_DISK_USAGE,
29 | +/* END CAB MODIFICATION */
30 | SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
31 | SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
32 | SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL,
33 |
34 | === modified file 'sql/sql_parse.cc'
35 | --- sql/sql_parse.cc 2012-07-05 10:07:26 +0000
36 | +++ sql/sql_parse.cc 2012-08-14 16:09:27 +0000
37 | @@ -3542,6 +3542,13 @@ end_with_restore_list:
38 | case SQLCOM_SHOW_AUTHORS:
39 | res= mysqld_show_authors(thd);
40 | break;
41 | +/* BEGIN CAB MODIFICATION */
42 | +/* Reason for Modification: */
43 | +/* Add SQLCOM_SHOW_DISK_USAGE case statement */
44 | + case SQLCOM_SHOW_DISK_USAGE:
45 | + res = show_disk_usage_command(thd);
46 | + break;
47 | +/* END CAB MODIFICATION */
48 | case SQLCOM_SHOW_CONTRIBUTORS:
49 | res= mysqld_show_contributors(thd);
50 | break;
51 |
52 | === modified file 'sql/sql_show.cc'
53 | --- sql/sql_show.cc 2012-07-10 14:32:03 +0000
54 | +++ sql/sql_show.cc 2012-08-14 17:24:19 +0000
55 | @@ -280,6 +280,89 @@ bool mysqld_show_authors(THD *thd)
56 | }
57 |
58 |
59 | +/* BEGIN CAB MODIFICATION */
60 | +/* Reason for Modification: */
61 | +/* Add show disk usage method */
62 | +bool show_disk_usage_command(THD *thd)
63 | +{
64 | + List- field_list;
65 | + List dbs;
66 | + LEX_STRING *db_name;
67 | + char *path;
68 | + MY_DIR *dirp;
69 | + FILEINFO *file;
70 | + longlong fsizes = 0;
71 | + longlong lsizes = 0;
72 | + Protocol *protocol= thd->protocol;
73 | + DBUG_ENTER("show_disk_usage");
74 | +
75 | + /* send the fields "Database" and "Size" */
76 | + field_list.push_back(new Item_empty_string("Database",50));
77 | + field_list.push_back(new Item_return_int("Size (Kb)", 7, MYSQL_TYPE_LONG));
78 | + if (protocol->send_result_set_metadata(&field_list,
79 | + Protocol::SEND_NUM_ROWS |
80 | + Protocol::SEND_EOF))
81 | + DBUG_RETURN(TRUE);
82 | +
83 | + /* get database directories */
84 | + find_files_result res = find_files(thd, &dbs, 0, mysql_data_home, 0, 1);
85 | + if (res != FIND_FILES_OK)
86 | + DBUG_RETURN(1);
87 | +
88 | + List_iterator_fast it_dbs(dbs);
89 | + path = (char *)my_malloc(PATH_MAX, MYF(MY_ZEROFILL));
90 | + dirp = my_dir(mysql_data_home, MYF(MY_WANT_STAT));
91 | + fsizes = 0;
92 | + for (int i = 0; i < (int)dirp->number_off_files; i++)
93 | + {
94 | + file = dirp->dir_entry + i;
95 | + if (strncasecmp(file->name, "ibdata", 6) == 0)
96 | + fsizes = fsizes + file->mystat->st_size;
97 | + else if (strncasecmp(file->name, "ib", 2) == 0)
98 | + lsizes = lsizes + file->mystat->st_size;
99 | + }
100 | +
101 | + /* send InnoDB data to client */
102 | + protocol->prepare_for_resend();
103 | + protocol->store("InnoDB TableSpace", system_charset_info);
104 | + protocol->store((longlong)fsizes);
105 | + if (protocol->write())
106 | + DBUG_RETURN(TRUE);
107 | + protocol->prepare_for_resend();
108 | + protocol->store("InnoDB Logs", system_charset_info);
109 | + protocol->store((longlong)lsizes);
110 | + if (protocol->write())
111 | + DBUG_RETURN(TRUE);
112 | +
113 | + /* now send database name and sizes of the databases */
114 | + while ((db_name = it_dbs++))
115 | + {
116 | + fsizes = 0;
117 | + strcpy(path, mysql_data_home);
118 | + strcat(path, "/");
119 | + strcat(path, db_name->str);
120 | + dirp = my_dir(path, MYF(MY_WANT_STAT));
121 | + for (int i = 0; i < (int)dirp->number_off_files; i++)
122 | + {
123 | + file = dirp->dir_entry + i;
124 | + fsizes = fsizes + file->mystat->st_size;
125 | + }
126 | +
127 | + protocol->prepare_for_resend();
128 | + protocol->store(db_name->str, system_charset_info);
129 | + protocol->store((longlong)fsizes);
130 | + if (protocol->write())
131 | + DBUG_RETURN(TRUE);
132 | + }
133 | + my_eof(thd);
134 | +
135 | + /* free memory */
136 | + my_free(path);
137 | + DBUG_RETURN(FALSE);
138 | + }
139 | +
140 | +/* END CAB MODIFICATION */
141 | +
142 | /***************************************************************************
143 | ** List all Contributors.
144 | ** Please get permission before updating
145 |
146 | === modified file 'sql/sql_show.h'
147 | --- sql/sql_show.h 2012-05-16 06:42:17 +0000
148 | +++ sql/sql_show.h 2012-08-14 16:09:27 +0000
149 | @@ -179,6 +179,11 @@ int mysqld_show_status(THD *thd);
150 | int mysqld_show_variables(THD *thd,const char *wild);
151 | bool mysqld_show_storage_engines(THD *thd);
152 | bool mysqld_show_authors(THD *thd);
153 | +/* BEGIN CAB MODIFICATION */
154 | +/* Reason for Modification: */
155 | +/* Add show disk usage method reference */
156 | +bool show_disk_usage_command(THD *thd);
157 | +/* END CAB MODIFICATION */
158 | bool mysqld_show_contributors(THD *thd);
159 | bool mysqld_show_privileges(THD *thd);
160 | char *make_backup_log_name(char *buff, const char *name, const char* log_ext);
161 |
162 | === modified file 'sql/sql_yacc.yy'
163 | --- sql/sql_yacc.yy 2012-07-13 08:50:05 +0000
164 | +++ sql/sql_yacc.yy 2012-08-14 16:09:27 +0000
165 | @@ -1145,6 +1145,11 @@ bool my_yyoverflow(short **a, YYSTYPE **
166 | %token DISABLE_SYM
167 | %token DISCARD
168 | %token DISK_SYM
169 | +/* BEGIN CAB MODIFICATION */
170 | +/* Reason for Modification: */
171 | +/* Add DISK_USAGE symbol */
172 | +%token DISK_USAGE_SYM
173 | +/* END CAB MODIFICATION */
174 | %token DISTINCT /* SQL-2003-R */
175 | %token DIV_SYM
176 | %token DOUBLE_SYM /* SQL-2003-R */
177 | @@ -12279,6 +12284,16 @@ opt_profile_args:
178 | /* Show things */
179 |
180 | show:
181 | +/* BEGIN CAB MODIFICATION */
182 | +/* Reason for Modification: */
183 | +/* Add show disk usage symbol parsing */
184 | + SHOW DISK_USAGE_SYM
185 | + {
186 | + LEX *lex=Lex;
187 | + lex->sql_command= SQLCOM_SHOW_DISK_USAGE;
188 | + }
189 | + |
190 | +/* END CAB MODIFICATION */
191 | SHOW
192 | {
193 | LEX *lex=Lex;
194 |
195 |
--------------------------------------------------------------------------------
/Ch07/diskusage_is.diff:
--------------------------------------------------------------------------------
1 | === modified file 'sql/handler.h'
2 | --- sql/handler.h 2012-06-11 11:30:25 +0000
3 | +++ sql/handler.h 2012-08-14 17:38:22 +0000
4 | @@ -679,6 +679,7 @@ enum enum_schema_tables
5 | SCH_COLLATION_CHARACTER_SET_APPLICABILITY,
6 | SCH_COLUMNS,
7 | SCH_COLUMN_PRIVILEGES,
8 | + SCH_DISKUSAGE,
9 | SCH_ENGINES,
10 | SCH_EVENTS,
11 | SCH_FILES,
12 |
13 | === modified file 'sql/sql_parse.cc'
14 | --- sql/sql_parse.cc 2012-07-05 10:07:26 +0000
15 | +++ sql/sql_parse.cc 2012-08-14 17:38:22 +0000
16 | @@ -1872,6 +1872,7 @@ int prepare_schema_table(THD *thd, LEX *
17 | DBUG_ENTER("prepare_schema_table");
18 |
19 | switch (schema_table_idx) {
20 | + case SCH_DISKUSAGE:
21 | case SCH_SCHEMATA:
22 | #if defined(DONT_ALLOW_SHOW_COMMANDS)
23 | my_message(ER_NOT_ALLOWED_COMMAND,
24 |
25 | === modified file 'sql/sql_show.cc'
26 | --- sql/sql_show.cc 2012-07-10 14:32:03 +0000
27 | +++ sql/sql_show.cc 2012-08-14 17:38:22 +0000
28 | @@ -7357,6 +7357,12 @@ int hton_fill_schema_table(THD *thd, TAB
29 | DBUG_RETURN(0);
30 | }
31 |
32 | +ST_FIELD_INFO disk_usage_fields_info[]=
33 | +{
34 | + {"DATABASE", 40, MYSQL_TYPE_STRING, 0, 0, "Database"},
35 | + {"SIZE (Kb)", 21 , MYSQL_TYPE_LONG, 0, 0, "Size (Kb)"},
36 | + {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
37 | +};
38 |
39 | ST_FIELD_INFO schema_fields_info[]=
40 | {
41 | @@ -8001,6 +8007,74 @@ ST_FIELD_INFO tablespaces_fields_info[]=
42 | /** For creating fields of information_schema.OPTIMIZER_TRACE */
43 | extern ST_FIELD_INFO optimizer_trace_info[];
44 |
45 | +int fill_disk_usage(THD *thd, TABLE_LIST *tables, Item *cond)
46 | +{
47 | + TABLE *table= tables->table;
48 | + CHARSET_INFO *scs= system_charset_info;
49 | + List
- field_list;
50 | + List dbs;
51 | + LEX_STRING *db_name;
52 | + char *path;
53 | + MY_DIR *dirp;
54 | + FILEINFO *file;
55 | + longlong fsizes = 0;
56 | + longlong lsizes = 0;
57 | + DBUG_ENTER("fill_disk_usage");
58 | +
59 | + find_files_result res = find_files(thd, &dbs, 0, mysql_data_home, 0, 1);
60 | + if (res != FIND_FILES_OK)
61 | + DBUG_RETURN(1);
62 | +
63 | + List_iterator_fast it_dbs(dbs);
64 | + path = (char *)my_malloc(PATH_MAX, MYF(MY_ZEROFILL));
65 | + dirp = my_dir(mysql_data_home, MYF(MY_WANT_STAT));
66 | + fsizes = 0;
67 | + for (int i = 0; i < (int)dirp->number_off_files; i++)
68 | + {
69 | + file = dirp->dir_entry + i;
70 | + if (strncasecmp(file->name, "ibdata", 6) == 0)
71 | + fsizes = fsizes + file->mystat->st_size;
72 | + else if (strncasecmp(file->name, "ib", 2) == 0)
73 | + lsizes = lsizes + file->mystat->st_size;
74 | + }
75 | +
76 | + /* send InnoDB data to client */
77 | + table->field[0]->store("InnoDB TableSpace", strlen("InnoDB TableSpace"), scs);
78 | + table->field[1]->store((longlong)fsizes, TRUE);
79 | +if (schema_table_store_record(thd, table))
80 | + DBUG_RETURN(1);
81 | + table->field[0]->store("InnoDB Logs", strlen("InnoDB Logs"), scs);
82 | + table->field[1]->store((longlong)lsizes, TRUE);
83 | + if (schema_table_store_record(thd, table))
84 | + DBUG_RETURN(1);
85 | +
86 | + /* now send database name and sizes of the databases */
87 | + while ((db_name = it_dbs++))
88 | + {
89 | + fsizes = 0;
90 | + strcpy(path, mysql_data_home);
91 | + strcat(path, "/");
92 | + strcat(path, db_name->str);
93 | + dirp = my_dir(path, MYF(MY_WANT_STAT));
94 | + for (int i = 0; i < (int)dirp->number_off_files; i++)
95 | + {
96 | + file = dirp->dir_entry + i;
97 | + fsizes = fsizes + file->mystat->st_size;
98 | + }
99 | + restore_record(table, s->default_values);
100 | +
101 | + table->field[0]->store(db_name->str, db_name->length, scs);
102 | + table->field[1]->store((longlong)fsizes, TRUE);
103 | + if (schema_table_store_record(thd, table))
104 | + DBUG_RETURN(1);
105 | + }
106 | +
107 | + /* free memory */
108 | + my_free(path);
109 | + DBUG_RETURN(0);
110 | +}
111 | +
112 | +
113 | /*
114 | Description of ST_FIELD_INFO in table.h
115 |
116 | @@ -8023,6 +8097,8 @@ ST_SCHEMA_TABLE schema_tables[]=
117 | fill_schema_column_privileges, 0, 0, -1, -1, 0, 0},
118 | {"ENGINES", engines_fields_info, create_schema_table,
119 | fill_schema_engines, make_old_format, 0, -1, -1, 0, 0},
120 | + {"DISKUSAGE", disk_usage_fields_info, create_schema_table,
121 | + fill_disk_usage, make_old_format, 0, -1, -1, 0, 0},
122 | #ifdef HAVE_EVENT_SCHEDULER
123 | {"EVENTS", events_fields_info, create_schema_table,
124 | Events::fill_schema_events, make_old_format, 0, -1, -1, 0, 0},
125 |
126 |
--------------------------------------------------------------------------------
/Ch07/gregorian.diff:
--------------------------------------------------------------------------------
1 | === modified file 'sql/item_create.cc'
2 | --- sql/item_create.cc 2012-06-28 10:46:42 +0000
3 | +++ sql/item_create.cc 2012-08-14 13:58:16 +0000
4 | @@ -2009,6 +2009,21 @@ protected:
5 | virtual ~Create_func_quote() {}
6 | };
7 |
8 | +/* BEGIN CAB MODIFICATION */
9 | +/* Reason for Modification: */
10 | +/* Add gregorian class definition */
11 | +class Create_func_gregorian : public Create_func_arg1
12 | +{
13 | +public:
14 | + virtual Item *create(THD *thd, Item *arg1);
15 | +
16 | + static Create_func_gregorian s_singleton;
17 | +
18 | +protected:
19 | + Create_func_gregorian() {}
20 | + virtual ~Create_func_gregorian() {}
21 | +};
22 | +/* END CAB MODIFICATION */
23 |
24 | class Create_func_radians : public Create_func_arg1
25 | {
26 | @@ -4762,6 +4777,17 @@ Create_func_quote::create(THD *thd, Item
27 | return new (thd->mem_root) Item_func_quote(arg1);
28 | }
29 |
30 | +/* BEGIN CAB MODIFICATION */
31 | +/* Reason for Modification: */
32 | +/* Add gregorian singleton create method */
33 | +Create_func_gregorian Create_func_gregorian::s_singleton;
34 | +
35 | +Item*
36 | +Create_func_gregorian::create(THD *thd, Item *arg1)
37 | +{
38 | + return new (thd->mem_root) Item_func_gregorian(arg1);
39 | +}
40 | +/* END CAB MODIFICATION */
41 |
42 | Create_func_radians Create_func_radians::s_singleton;
43 |
44 | @@ -5547,6 +5573,11 @@ static Native_func_registry func_array[]
45 | { { C_STRING_WITH_LEN("POW") }, BUILDER(Create_func_pow)},
46 | { { C_STRING_WITH_LEN("POWER") }, BUILDER(Create_func_pow)},
47 | { { C_STRING_WITH_LEN("QUOTE") }, BUILDER(Create_func_quote)},
48 | +/* BEGIN CAB MODIFICATION */
49 | +/* Reason for Modification: */
50 | +/* Add gregorian symbol */
51 | + { { C_STRING_WITH_LEN("GREGORIAN") }, BUILDER(Create_func_gregorian)},
52 | +/* END CAB MODIFICATION */
53 | { { C_STRING_WITH_LEN("RADIANS") }, BUILDER(Create_func_radians)},
54 | { { C_STRING_WITH_LEN("RAND") }, BUILDER(Create_func_rand)},
55 | { { C_STRING_WITH_LEN("RELEASE_LOCK") }, BUILDER(Create_func_release_lock)},
56 |
57 | === modified file 'sql/item_strfunc.cc'
58 | --- sql/item_strfunc.cc 2012-06-11 11:30:25 +0000
59 | +++ sql/item_strfunc.cc 2012-08-14 13:58:16 +0000
60 | @@ -4031,6 +4031,50 @@ null:
61 | return 0;
62 | }
63 |
64 | +/* BEGIN CAB MODIFICATION */
65 | +/* Reason for Modification: */
66 | +/* Add gregorian function code */
67 | +String *Item_func_gregorian::val_str(String *str)
68 | +{
69 | + static int DAYS_IN_MONTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
70 | + longlong jdate = args[0]->val_int();
71 | + int year = 0;
72 | + int month = 0;
73 | + int day = 0;
74 | + int i;
75 | + char cstr[30];
76 | + cstr[0] = 0;
77 | + str->length(0);
78 | +
79 | + /* get date from value (right 4 digits */
80 | + year = jdate - ((jdate / 10000) * 10000);
81 | +
82 | + /* get value for day of year and find current month*/
83 | + day = (jdate - year) / 10000;
84 | + for (i = 0; i < 12; i++)
85 | + if (DAYS_IN_MONTH[i] < day)
86 | + day = day - DAYS_IN_MONTH[i]; /* remainder is day of current month */
87 | + else
88 | + {
89 | + month = i + 1;
90 | + break;
91 | + }
92 | +
93 | + /* format date string */
94 | + sprintf(cstr, "%d", month);
95 | + str->append(cstr);
96 | + str->append("/");
97 | + sprintf(cstr, "%d", day);
98 | + str->append(cstr);
99 | + str->append("/");
100 | + sprintf(cstr, "%d", year);
101 | + str->append(cstr);
102 | + if (null_value)
103 | + return 0;
104 | + return str;
105 | +}
106 | +/* END CAB MODIFICATION */
107 | +
108 | longlong Item_func_uncompressed_length::val_int()
109 | {
110 | DBUG_ASSERT(fixed == 1);
111 |
112 | === modified file 'sql/item_strfunc.h'
113 | --- sql/item_strfunc.h 2012-07-06 15:16:34 +0000
114 | +++ sql/item_strfunc.h 2012-08-14 13:58:16 +0000
115 | @@ -847,6 +847,23 @@ public:
116 | }
117 | };
118 |
119 | +/* BEGIN CAB MODIFICATION */
120 | +/* Reason for Modification: */
121 | +/* Add gregorian Item function code */
122 | +class Item_func_gregorian :public Item_str_func
123 | +{
124 | + String tmp_value;
125 | +public:
126 | + Item_func_gregorian(Item *a) :Item_str_func(a) {}
127 | + const char *func_name() const { return "gregorian"; }
128 | + String *val_str(String *);
129 | + void fix_length_and_dec()
130 | + {
131 | + max_length=30;
132 | + }
133 | +};
134 | +/* END CAB MODIFICATION */
135 | +
136 | class Item_func_conv_charset :public Item_str_func
137 | {
138 | bool use_cached_value;
139 |
140 |
--------------------------------------------------------------------------------
/Ch07/julian.diff:
--------------------------------------------------------------------------------
1 | === modified file 'sql/udf_example.cc'
2 | --- sql/udf_example.cc 2011-12-09 21:08:37 +0000
3 | +++ sql/udf_example.cc 2012-08-13 23:45:19 +0000
4 | @@ -166,6 +166,9 @@ double avgcost( UDF_INIT* initid, UDF_AR
5 | my_bool is_const_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
6 | char *is_const(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long
7 | *length, char *is_null, char *error);
8 | +my_bool julian_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
9 | +longlong julian(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error);
10 | +void julian_deinit(UDF_INIT *initid);
11 | C_MODE_END;
12 |
13 | /*************************************************************************
14 | @@ -1142,6 +1145,61 @@ char * check_const_len(UDF_INIT *initid,
15 | return result;
16 | }
17 |
18 | +extern "C" my_bool julian_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
19 | +{
20 | + if (args->arg_count != 3) /* if there are not three arguments */
21 | + {
22 | + strcpy(message, "Wrong number of arguments: JULIAN() requires 3 arguments.");
23 | + return 1;
24 | + }
25 | + if ((args->arg_type[0] != INT_RESULT) ||
26 | + (args->arg_type[1] != INT_RESULT) ||
27 | + (args->arg_type[2] != INT_RESULT))
28 | + {
29 | + strcpy(message, "Wrong type of arguments: JULIAN() requires 3 integers.");
30 | + return 1;
31 | + }
32 | + return 0;
33 | +}
34 | +
35 | +extern "C" void julian_deinit(UDF_INIT *initid)
36 | +{
37 | +}
38 | +
39 | +
40 | +extern "C" longlong julian(UDF_INIT *initid, UDF_ARGS *args, char *is_null, char *error)
41 | +{
42 | + longlong jdate = 0;
43 | + static int DAYS_IN_MONTH[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
44 | + int month = 0;
45 | + int day = 0;
46 | + int year = 0;
47 | + int i;
48 | +
49 | + /* copy memory from the arguments */
50 | + memcpy(&month, args->args[0], args->lengths[0]);
51 | + memcpy(&day, args->args[1], args->lengths[1]);
52 | + memcpy(&year, args->args[2], args->lengths[2]);
53 | +
54 | + /* add the days in the month for each prior month */
55 | + for (i = 0; i < month - 1; i++)
56 | + jdate += DAYS_IN_MONTH[i];
57 | +
58 | + /* add the day of this month */
59 | + jdate += day;
60 | +
61 | + /* find the year */
62 | + if (((year % 100) != 0) && ((year % 4) == 0))
63 | + jdate++; /*leap year!*/
64 | +
65 | + /* shift day of year to left */
66 | + jdate *= 10000;
67 | +
68 | + /* add the year */
69 | + jdate += year;
70 | + return jdate;
71 | +}
72 | +
73 |
74 | C_MODE_START;
75 | my_bool my_median_init (UDF_INIT *initid, UDF_ARGS *args, char *message);
76 |
77 | === modified file 'sql/udf_example.def'
78 | --- sql/udf_example.def 2011-10-11 04:27:52 +0000
79 | +++ sql/udf_example.def 2012-08-13 22:51:32 +0000
80 | @@ -30,3 +30,6 @@ EXPORTS
81 | my_median_add
82 | my_median_clear
83 | my_median
84 | + julian_init
85 | + julian_deinit
86 | + julian
87 | \ No newline at end of file
88 |
89 |
--------------------------------------------------------------------------------
/Ch07/source_Ch07.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch07/source_Ch07.zip
--------------------------------------------------------------------------------
/Ch08/source_Ch08.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch08/source_Ch08.zip
--------------------------------------------------------------------------------
/Ch08/stop_slaves.diff:
--------------------------------------------------------------------------------
1 | === modified file 'sql/lex.h'
2 | --- sql/lex.h 2012-05-03 08:35:47 +0000
3 | +++ sql/lex.h 2012-08-25 17:48:07 +0000
4 | @@ -519,6 +519,11 @@ static SYMBOL symbols[] = {
5 | { "SIGNED", SYM(SIGNED_SYM)},
6 | { "SIMPLE", SYM(SIMPLE_SYM)},
7 | { "SLAVE", SYM(SLAVE)},
8 | +/* BEGIN CAB MODIFICATION */
9 | +/* Reason for Modification: */
10 | +/* Add SLAVES keyword */
11 | + { "SLAVES", SYM(SLAVES)},
12 | +/* END CAB MODIFICATION */
13 | { "SLOW", SYM(SLOW)},
14 | { "SNAPSHOT", SYM(SNAPSHOT_SYM)},
15 | { "SMALLINT", SYM(SMALLINT)},
16 |
17 | === modified file 'sql/sql_cmd.h'
18 | --- sql/sql_cmd.h 2012-05-28 09:09:33 +0000
19 | +++ sql/sql_cmd.h 2012-08-25 17:48:07 +0000
20 | @@ -53,7 +53,11 @@ enum enum_sql_command {
21 | SQLCOM_FLUSH, SQLCOM_KILL, SQLCOM_ANALYZE,
22 | SQLCOM_ROLLBACK, SQLCOM_ROLLBACK_TO_SAVEPOINT,
23 | SQLCOM_COMMIT, SQLCOM_SAVEPOINT, SQLCOM_RELEASE_SAVEPOINT,
24 | - SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP,
25 | +/* BEGIN CAB MODIFICATION */
26 | +/* Reason for Modification: */
27 | +/* Add SQLCOM_STOP_SLAVES enum */
28 | + SQLCOM_SLAVE_START, SQLCOM_SLAVE_STOP, SQLCOM_STOP_SLAVES,
29 | +/* END CAB MODIFICATION */
30 | SQLCOM_BEGIN, SQLCOM_CHANGE_MASTER,
31 | SQLCOM_RENAME_TABLE,
32 | SQLCOM_RESET, SQLCOM_PURGE, SQLCOM_PURGE_BEFORE, SQLCOM_SHOW_BINLOGS,
33 |
34 | === modified file 'sql/sql_parse.cc'
35 | --- sql/sql_parse.cc 2012-07-05 10:07:26 +0000
36 | +++ sql/sql_parse.cc 2012-08-25 17:48:07 +0000
37 | @@ -3054,6 +3054,18 @@ end_with_restore_list:
38 | mysql_mutex_unlock(&LOCK_active_mi);
39 | break;
40 | }
41 | +
42 | +/* BEGIN CAB MODIFICATION */
43 | +/* Reason for Modification: */
44 | +/* Add case statement for STOP ALL SLAVES command */
45 | + case SQLCOM_STOP_SLAVES:
46 | + {
47 | + if (!lex->no_write_to_binlog)
48 | + res= write_bin_log(thd, TRUE, "STOP SLAVE IO_THREAD", 20);
49 | + break;
50 | + }
51 | +/* END CAB MODIFICATION */
52 | +
53 | #endif /* HAVE_REPLICATION */
54 |
55 | case SQLCOM_RENAME_TABLE:
56 |
57 | === modified file 'sql/sql_yacc.yy'
58 | --- sql/sql_yacc.yy 2012-07-13 08:50:05 +0000
59 | +++ sql/sql_yacc.yy 2012-08-25 18:10:24 +0000
60 | @@ -1497,6 +1497,11 @@ bool my_yyoverflow(short **a, YYSTYPE **
61 | %token SIGNED_SYM
62 | %token SIMPLE_SYM /* SQL-2003-N */
63 | %token SLAVE
64 | +/* BEGIN CAB MODIFICATION */
65 | +/* Reason for Modification: */
66 | +/* Add SLAVES token */
67 | +%token SLAVES
68 | +/* END CAB MODIFICATION */
69 | %token SLOW
70 | %token SMALLINT /* SQL-2003-R */
71 | %token SNAPSHOT_SYM
72 | @@ -1808,7 +1813,11 @@ bool my_yyoverflow(short **a, YYSTYPE **
73 | show describe load alter optimize keycache preload flush
74 | reset purge begin commit rollback savepoint release
75 | slave master_def master_defs master_file_def slave_until_opts
76 | - repair analyze check start checksum
77 | +/* BEGIN CAB MODIFICATION */
78 | +/* Reason for Modification: */
79 | +/* Add stop to list of NONE types */
80 | + repair analyze check start stop checksum
81 | +/* END CAB MODIFICATION */
82 | field_list field_list_item field_spec kill column_def key_def
83 | keycache_list keycache_list_or_parts assign_to_keycache
84 | assign_to_keycache_parts
85 | @@ -2026,6 +2035,11 @@ statement:
86 | | show
87 | | slave
88 | | start
89 | +/* BEGIN CAB MODIFICATION */
90 | +/* Reason for Modification: */
91 | +/* Add stop to list of statement targets */
92 | + | stop
93 | +/* END CAB MODIFICATION */
94 | | truncate
95 | | uninstall
96 | | unlock
97 | @@ -8013,6 +8027,18 @@ slave:
98 | }
99 | ;
100 |
101 | +/* BEGIN CAB MODIFICATION */
102 | +/* Reason for Modification: */
103 | +/* Add rule for STOP ALL SLAVES command */
104 | +stop:
105 | + STOP_SYM ALL SLAVES
106 | + {
107 | + LEX *lex=Lex;
108 | + lex->sql_command = SQLCOM_STOP_SLAVES;
109 | + }
110 | + ;
111 | +/* END CAB MODIFICATION */
112 | +
113 | start:
114 | START_SYM TRANSACTION_SYM opt_start_transaction_option_list
115 | {
116 |
117 |
--------------------------------------------------------------------------------
/Ch09/rfid_auth/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # cmake configuration file for the RFID Authentication Plugin
2 |
3 | MYSQL_ADD_PLUGIN(rfid_auth rfid_auth.cc
4 | MODULE_ONLY MODULE_OUTPUT_NAME "rfid_auth")
5 |
6 | INSTALL(FILES rfid_auth.ini DESTINATION ${INSTALL_PLUGINDIR})
7 |
--------------------------------------------------------------------------------
/Ch09/rfid_auth/rfid_auth.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 | #include
10 | #include
11 |
12 | #ifndef __WIN__
13 |
14 | #include
15 | #include
16 |
17 | #else
18 |
19 | #include
20 | #include
21 | #include
22 | #include
23 | using namespace std;
24 |
25 | /*
26 | Get password with no echo.
27 | */
28 | char *getpass(const char *prompt)
29 | {
30 | string pass ="";
31 | char ch;
32 | cout << prompt;
33 | ch = _getch();
34 | while(ch != 13) //character 13 is enter key
35 | {
36 | pass.push_back(ch);
37 | ch = _getch();
38 | }
39 | return (char *)pass.c_str();
40 | }
41 |
42 | #endif
43 |
44 | #define MAX_RFID_CODE 12
45 | #define MAX_BUFFER 255
46 | #define MAX_PIN 16
47 |
48 | /* Client-side plugin */
49 |
50 |
51 | /*
52 | * Read a RFID code from the serial port.
53 | */
54 | #ifndef __WIN__
55 | unsigned char *get_rfid_code(char *port)
56 | {
57 | int fd;
58 | unsigned char *rfid_code= NULL;
59 | int nbytes;
60 | unsigned char raw_buff[MAX_BUFFER];
61 | unsigned char *bufptr = NULL;
62 |
63 | fd = open(port, O_RDWR | O_NOCTTY | O_NDELAY);
64 | if (fd == -1)
65 | {
66 | printf("Unable to open port: %s.\n", port);
67 | return NULL;
68 | }
69 | else
70 | fcntl(fd, F_SETFL, 0);
71 |
72 | bufptr = raw_buff;
73 | while ((nbytes = read(fd, bufptr, raw_buff + sizeof(raw_buff) - bufptr - 1)) > 0)
74 | {
75 | bufptr += nbytes;
76 | if (bufptr[-1] == '\n' || bufptr[-2] == '\n' || bufptr[-3] == '\n' ||
77 | bufptr[-1] == '\r' || bufptr[-2] == '\r' || bufptr[-3] == '\r' ||
78 | bufptr[-1] == 0x03 || bufptr[-2] == 0x03 || bufptr[-3] == 0x03)
79 | break;
80 | }
81 | *bufptr = '\0';
82 |
83 | rfid_code = (unsigned char *)strdup((char *)raw_buff);
84 | return rfid_code;
85 | }
86 |
87 | #else
88 |
89 | unsigned char *get_rfid_code(char *port)
90 | {
91 | HANDLE com_port;
92 | DWORD nbytes;
93 | unsigned char raw_buff[MAX_BUFFER];
94 | unsigned char *rfid_code= NULL;
95 |
96 | /* Open the port specified. */
97 | com_port = CreateFile(port, GENERIC_READ, 0, 0, OPEN_EXISTING,
98 | FILE_ATTRIBUTE_NORMAL, 0);
99 | if (com_port == INVALID_HANDLE_VALUE)
100 | {
101 | int error = GetLastError();
102 | if (error == ERROR_FILE_NOT_FOUND)
103 | {
104 | printf("Unable to open port: %s.\n", port);
105 | return NULL;
106 | }
107 | printf("Error opening port: %s:%d.\n", port, error);
108 | return NULL;
109 | }
110 |
111 | /* Configure the port. */
112 | DCB com_config = {0};
113 | com_config.DCBlength = sizeof(com_config);
114 | if (!GetCommState(com_port, &com_config))
115 | {
116 | printf("Unable to get port state.\n");
117 | return NULL;
118 | }
119 | com_config.BaudRate = CBR_9600;
120 | com_config.ByteSize = 8;
121 | com_config.Parity = NOPARITY;
122 | com_config.StopBits = ONESTOPBIT;
123 | if (!SetCommState(com_port, &com_config))
124 | {
125 | printf("Unable to set port state.\n");
126 | return NULL;
127 | }
128 |
129 | /* Set timeouts. */
130 | COMMTIMEOUTS timeouts = {0};
131 | timeouts.ReadIntervalTimeout=50;
132 | timeouts.ReadTotalTimeoutConstant=50;
133 | timeouts.ReadTotalTimeoutMultiplier=10;
134 | if (!SetCommTimeouts(com_port, &timeouts))
135 | {
136 | printf("Cannot set timeouts for port.\n");
137 | return NULL;
138 | }
139 |
140 | /* Read from the port. */
141 | if (!ReadFile(com_port, raw_buff, MAX_BUFFER, &nbytes, NULL))
142 | {
143 | printf("Unable to read from the port.\n");
144 | return NULL;
145 | }
146 |
147 | /* Close the port. */
148 | CloseHandle(com_port);
149 |
150 | rfid_code = (unsigned char *)strdup((char *)raw_buff);
151 | return rfid_code;
152 | }
153 |
154 | #endif /* __WIN__ */
155 |
156 | static int rfid_send(MYSQL_PLUGIN_VIO *vio, st_mysql *mysql)
157 | {
158 | char *port= 0;
159 | char pass[MAX_PIN];
160 | int len, res;
161 | unsigned char buffer[MAX_BUFFER];
162 | unsigned char *raw_buff= NULL;
163 | int start= 0;
164 |
165 | /* Get the port to open. */
166 | port= getenv("MYSQL_RFID_PORT");
167 | if (!port)
168 | {
169 | printf("Environment variable not set.\n");
170 | return CR_ERROR;
171 | }
172 |
173 | printf("Please swipe your card now...\n");
174 |
175 | raw_buff = get_rfid_code(port);
176 | if (raw_buff == NULL)
177 | {
178 | printf("Cannot read RFID code.\n");
179 | return CR_ERROR;
180 | }
181 | len = strlen((char *)raw_buff);
182 |
183 | // Strip off leading extra bytes.
184 | for (int j= 0; j < 2; j++)
185 | if (raw_buff[j] == 0x02 || raw_buff[j] == 0x03)
186 | start++;
187 |
188 | strncpy((char *)buffer, (char *)raw_buff+start, len-start);
189 | len = strlen((char *)buffer);
190 | /* Check for valid read. */
191 | if (len >= MAX_RFID_CODE)
192 | {
193 | // Strip off extra bytes at end (CR, LF, etc)
194 | buffer[MAX_RFID_CODE] = '\0';
195 | len = MAX_RFID_CODE;
196 | }
197 | else
198 | {
199 | printf("RFID code length error. Please try again.\n");
200 | return CR_ERROR;
201 | }
202 |
203 | strncpy(pass, getpass("Please enter your PIN: "), sizeof(pass));
204 | strcat((char *)buffer, pass);
205 | len = strlen((char *)buffer);
206 |
207 | res= vio->write_packet(vio, buffer, len);
208 |
209 | return res ? CR_ERROR : CR_OK;
210 | }
211 |
212 | mysql_declare_client_plugin(AUTHENTICATION)
213 | "rfid_auth",
214 | "Chuck Bell",
215 | "RFID Authentication Plugin - Client",
216 | {0, 0, 1},
217 | "GPL",
218 | NULL,
219 | NULL,
220 | NULL,
221 | NULL,
222 | rfid_send
223 | mysql_end_client_plugin;
224 |
225 |
226 | /*
227 | * Server-side plugin
228 | */
229 | static int rfid_auth_validate(MYSQL_PLUGIN_VIO *vio,
230 | MYSQL_SERVER_AUTH_INFO *info)
231 | {
232 | unsigned char *pkt;
233 | int pkt_len, err= CR_OK;
234 |
235 | if ((pkt_len= vio->read_packet(vio, &pkt)) < 0)
236 | return CR_ERROR;
237 |
238 | info->password_used= PASSWORD_USED_YES;
239 |
240 | if (strcmp((const char *) pkt, info->auth_string))
241 | return CR_ERROR;
242 |
243 | return err;
244 | }
245 |
246 | static struct st_mysql_auth rfid_auth_handler=
247 | {
248 | MYSQL_AUTHENTICATION_INTERFACE_VERSION,
249 | "rfid_auth",
250 | rfid_auth_validate
251 | };
252 |
253 | mysql_declare_plugin(rfid_auth_plugin)
254 | {
255 | MYSQL_AUTHENTICATION_PLUGIN,
256 | &rfid_auth_handler,
257 | "rfid_auth",
258 | "Chuck Bell",
259 | "RFID Authentication Plugin - Server",
260 | PLUGIN_LICENSE_GPL,
261 | NULL,
262 | NULL,
263 | 0x0100,
264 | NULL,
265 | NULL,
266 | NULL,
267 | 0,
268 | }
269 | mysql_declare_plugin_end;
270 |
--------------------------------------------------------------------------------
/Ch09/rfid_auth/rfid_auth.ini:
--------------------------------------------------------------------------------
1 | #
2 | # Plugin configuration file. Place the following on a separate line:
3 | #
4 | # library binary file name (without .so or .dll)
5 | # component_name
6 | # [component_name] - additional components in plugin
7 | #
8 | librfid_auth
9 | rfid_auth
10 |
--------------------------------------------------------------------------------
/Ch09/source_Ch09.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch09/source_Ch09.zip
--------------------------------------------------------------------------------
/Ch10/source_Ch10.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch10/source_Ch10.zip
--------------------------------------------------------------------------------
/Ch10/stage_five/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Spartan storage engine plugin
2 |
3 | SET(SPARTAN_PLUGIN_STATIC "spartan")
4 | SET(SPARTAN_PLUGIN_DYNAMIC "spartan")
5 |
6 | SET(SPARTAN_SOURCES
7 | ha_spartan.cc ha_spartan.h
8 | spartan_data.cc spartan_data.h
9 | spartan_index.cc spartan_index.h
10 | )
11 |
12 | MYSQL_ADD_PLUGIN(spartan ${SPARTAN_SOURCES} STORAGE_ENGINE MODULE_ONLY)
13 |
14 | TARGET_LINK_LIBRARIES(spartan mysys)
15 |
--------------------------------------------------------------------------------
/Ch10/stage_five/Ch10s5.test:
--------------------------------------------------------------------------------
1 | #
2 | # Simple test for the Spartan storage engine
3 | #
4 | --disable_warnings
5 | drop table if exists t1;
6 | --enable_warnings
7 |
8 | CREATE TABLE t1 (
9 | col_a int KEY,
10 | col_b varchar(20),
11 | col_c int
12 | ) ENGINE=SPARTAN;
13 |
14 | INSERT INTO t1 VALUES (1, "first test", 24);
15 | INSERT INTO t1 VALUES (2, "second test", 43);
16 | INSERT INTO t1 VALUES (9, "fourth test", -2);
17 | INSERT INTO t1 VALUES (3, 'eighth test', -22);
18 | INSERT INTO t1 VALUES (4, "tenth test", 11);
19 | INSERT INTO t1 VALUES (8, "seventh test", 20);
20 | INSERT INTO t1 VALUES (5, "third test", 100);
21 | SELECT * FROM t1;
22 | UPDATE t1 SET col_b = "Updated!" WHERE col_a = 1;
23 | SELECT * from t1;
24 | UPDATE t1 SET col_b = "Updated!" WHERE col_a = 3;
25 | SELECT * from t1;
26 | UPDATE t1 SET col_b = "Updated!" WHERE col_a = 5;
27 | SELECT * from t1;
28 | DELETE FROM t1 WHERE col_a = 1;
29 | SELECT * FROM t1;
30 | DELETE FROM t1 WHERE col_a = 3;
31 | SELECT * FROM t1;
32 | DELETE FROM t1 WHERE col_a = 5;
33 | SELECT * FROM t1;
34 | SELECT * FROM t1 WHERE col_a = 4;
35 | SELECT * FROM t1 WHERE col_a >= 2 AND col_a <= 5;
36 | SELECT * FROM t1 WHERE col_a = 22;
37 | DELETE FROM t1 WHERE col_a = 5;
38 | SELECT * FROM t1;
39 | SELECT * FROM t1 WHERE col_a = 5;
40 | UPDATE t1 SET col_a = 99 WHERE col_a = 8;
41 | SELECT * FROM t1 WHERE col_a = 8;
42 | SELECT * FROM t1 WHERE col_a = 99;
43 | RENAME TABLE t1 TO t2;
44 | SELECT * FROM t2;
45 | DROP TABLE t2;
46 |
--------------------------------------------------------------------------------
/Ch10/stage_five/ha_spartan.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan Storage Engine Plugin
3 | */
4 |
5 | #include "my_global.h" /* ulonglong */
6 | #include "thr_lock.h" /* THR_LOCK, THR_LOCK_DATA */
7 | #include "handler.h" /* handler */
8 | #include "spartan_data.h"
9 | #include "spartan_index.h"
10 |
11 | class Spartan_share : public Handler_share {
12 | public:
13 | mysql_mutex_t mutex;
14 | THR_LOCK lock;
15 | Spartan_data *data_class;
16 | Spartan_index *index_class;
17 | Spartan_share();
18 | ~Spartan_share()
19 | {
20 | thr_lock_delete(&lock);
21 | mysql_mutex_destroy(&mutex);
22 | if (data_class != NULL)
23 | delete data_class;
24 | data_class = NULL;
25 | if (index_class != NULL)
26 | delete index_class;
27 | index_class = NULL;
28 | }
29 | };
30 |
31 | /*
32 | Class definition for the storage engine
33 | */
34 | class ha_spartan: public handler
35 | {
36 | THR_LOCK_DATA lock; /* MySQL lock */
37 | Spartan_share *share; ///< Shared lock info
38 | Spartan_share *get_share(); ///< Get the share
39 | off_t current_position; /* Current position in the file during a file scan */
40 |
41 | public:
42 | ha_spartan(handlerton *hton, TABLE_SHARE *table_ar);
43 | ~ha_spartan()
44 | {
45 | }
46 | /* The name that will be used for display purposes */
47 | const char *table_type() const { return "SPARTAN"; }
48 | /*
49 | The name of the index type that will be used for display
50 | don't implement this method unless you really have indexes
51 | */
52 | const char *index_type(uint inx) { return "Spartan_index"; }
53 | /*
54 | The file extensions.
55 | */
56 | const char **bas_ext() const;
57 | /*
58 | This is a list of flags that says what the storage engine
59 | implements. The current table flags are documented in
60 | handler.h
61 | */
62 | ulonglong table_flags() const
63 | {
64 | return (HA_NO_BLOBS | HA_NO_AUTO_INCREMENT | HA_BINLOG_STMT_CAPABLE);
65 | }
66 | /*
67 | This is a bitmap of flags that says how the storage engine
68 | implements indexes. The current index flags are documented in
69 | handler.h. If you do not implement indexes, just return zero
70 | here.
71 |
72 | part is the key part to check. First key part is 0
73 | If all_parts it's set, MySQL want to know the flags for the combined
74 | index up to and including 'part'.
75 | */
76 | ulong index_flags(uint inx, uint part, bool all_parts) const
77 | {
78 | return (HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE |
79 | HA_READ_ORDER | HA_KEYREAD_ONLY);
80 | }
81 | /*
82 | unireg.cc will call the following to make sure that the storage engine can
83 | handle the data it is about to send.
84 |
85 | Return *real* limits of your storage engine here. MySQL will do
86 | min(your_limits, MySQL_limits) automatically
87 |
88 | There is no need to implement ..._key_... methods if you don't suport
89 | indexes.
90 | */
91 | uint max_supported_keys() const { return 1; }
92 | uint max_supported_key_parts() const { return 1; }
93 | uint max_supported_key_length() const { return 128; }
94 | /*
95 | Called in test_quick_select to determine if indexes should be used.
96 | */
97 | virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
98 | /*
99 | The next method will never be called if you do not implement indexes.
100 | */
101 | virtual double read_time(uint, uint, ha_rows rows)
102 | { return (double) rows / 20.0+1; }
103 |
104 | /*
105 | Everything below are methods that we implment in ha_spartan.cc.
106 |
107 | Most of these methods are not obligatory, skip them and
108 | MySQL will treat them as not implemented
109 | */
110 | int open(const char *name, int mode, uint test_if_locked); // required
111 | int close(void); // required
112 |
113 | int write_row(uchar * buf);
114 | int update_row(const uchar * old_data, uchar * new_data);
115 | int delete_row(const uchar * buf);
116 | int index_read_map(uchar *buf, const uchar *key,
117 | key_part_map keypart_map, enum ha_rkey_function find_flag);
118 | int index_next(uchar * buf);
119 | int index_prev(uchar * buf);
120 | int index_first(uchar * buf);
121 | int index_last(uchar * buf);
122 | /*
123 | unlike index_init(), rnd_init() can be called two times
124 | without rnd_end() in between (it only makes sense if scan=1).
125 | then the second call should prepare for the new table scan
126 | (e.g if rnd_init allocates the cursor, second call should
127 | position it to the start of the table, no need to deallocate
128 | and allocate it again
129 | */
130 | int rnd_init(bool scan); //required
131 | int rnd_end();
132 | int rnd_next(uchar *buf); //required
133 | int rnd_pos(uchar * buf, uchar *pos); //required
134 | void position(const uchar *record); //required
135 | int info(uint); //required
136 |
137 | int extra(enum ha_extra_function operation);
138 | int external_lock(THD *thd, int lock_type); //required
139 | int delete_all_rows(void);
140 | int truncate();
141 | ha_rows records_in_range(uint inx, key_range *min_key,
142 | key_range *max_key);
143 | int delete_table(const char *from);
144 | int rename_table(const char * from, const char * to);
145 | int create(const char *name, TABLE *form,
146 | HA_CREATE_INFO *create_info); //required
147 |
148 | THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
149 | enum thr_lock_type lock_type); //required
150 | uchar *get_key();
151 | int get_key_len();
152 | };
153 |
154 |
--------------------------------------------------------------------------------
/Ch10/stage_five/spartan_data.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan_data.h
3 |
4 | This header defines a simple data file class for reading raw data to and
5 | from disk. The data written is in byte format so it can be anything you
6 | want it to be. The write_row and read_row accept the length of the data
7 | item to be read.
8 | */
9 | #include "my_global.h"
10 | #include "my_sys.h"
11 |
12 | class Spartan_data
13 | {
14 | public:
15 | Spartan_data(void);
16 | ~Spartan_data(void);
17 | int create_table(char *path);
18 | int open_table(char *path);
19 | long long write_row(uchar *buf, int length);
20 | long long update_row(uchar *old_rec, uchar *new_rec,
21 | int length, long long position);
22 | int read_row(uchar *buf, int length, long long position);
23 | int delete_row(uchar *old_rec, int length, long long position);
24 | int close_table();
25 | long long cur_position();
26 | int records();
27 | int del_records();
28 | int trunc_table();
29 | int row_size(int length);
30 | private:
31 | File data_file;
32 | int header_size;
33 | int record_header_size;
34 | bool crashed;
35 | int number_records;
36 | int number_del_records;
37 | int read_header();
38 | int write_header();
39 | };
40 |
--------------------------------------------------------------------------------
/Ch10/stage_five/spartan_index.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan_index.h
3 |
4 | This header file defines a simple index class that can
5 | be used to store file pointer indexes (long long). The
6 | class keeps the entire index in memory for fast access.
7 | The internal memory structure is a linked list. While
8 | not as efficient as a btree, it should be usable for
9 | most testing environments. The constructor accepts the
10 | max key length. This is used for all nodes in the index.
11 |
12 | File Layout:
13 | SOF max_key_len (int)
14 | SOF + sizeof(int) crashed (bool)
15 | SOF + sizeof(int) + sizeof(bool) DATA BEGINS HERE
16 | */
17 | #include "my_global.h"
18 | #include "my_sys.h"
19 |
20 | const long METADATA_SIZE = sizeof(int) + sizeof(bool);
21 | /*
22 | This is the node that stores the key and the file
23 | position for the data row.
24 | */
25 | struct SDE_INDEX
26 | {
27 | uchar key[128];
28 | long long pos;
29 | int length;
30 | };
31 |
32 | /* defines (doubly) linked list for internal list */
33 | struct SDE_NDX_NODE
34 | {
35 | SDE_INDEX key_ndx;
36 | SDE_NDX_NODE *next;
37 | SDE_NDX_NODE *prev;
38 | };
39 |
40 | class Spartan_index
41 | {
42 | public:
43 | Spartan_index(int keylen);
44 | Spartan_index();
45 | ~Spartan_index(void);
46 | int open_index(char *path);
47 | int create_index(char *path, int keylen);
48 | int insert_key(SDE_INDEX *ndx, bool allow_dupes);
49 | int delete_key(uchar *buf, long long pos, int key_len);
50 | int update_key(uchar *buf, long long pos, int key_len);
51 | long long get_index_pos(uchar *buf, int key_len);
52 | long long get_first_pos();
53 | uchar *get_first_key();
54 | uchar *get_last_key();
55 | uchar *get_next_key();
56 | uchar *get_prev_key();
57 | int close_index();
58 | int load_index();
59 | int destroy_index();
60 | SDE_INDEX *seek_index(uchar *key, int key_len);
61 | SDE_NDX_NODE *seek_index_pos(uchar *key, int key_len);
62 | int save_index();
63 | int trunc_index();
64 | private:
65 | File index_file;
66 | int max_key_len;
67 | SDE_NDX_NODE *root;
68 | SDE_NDX_NODE *range_ptr;
69 | int block_size;
70 | bool crashed;
71 | int read_header();
72 | int write_header();
73 | long long write_row(SDE_INDEX *ndx);
74 | SDE_INDEX *read_row(long long Position);
75 | long long curfpos();
76 | };
77 |
--------------------------------------------------------------------------------
/Ch10/stage_four/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Spartan storage engine plugin
2 |
3 | SET(SPARTAN_PLUGIN_STATIC "spartan")
4 | SET(SPARTAN_PLUGIN_DYNAMIC "spartan")
5 |
6 | SET(SPARTAN_SOURCES ha_spartan.cc ha_spartan.h spartan_data.cc spartan_data.h)
7 |
8 | MYSQL_ADD_PLUGIN(spartan ${SPARTAN_SOURCES} STORAGE_ENGINE MODULE_ONLY)
9 |
10 | TARGET_LINK_LIBRARIES(spartan mysys)
11 |
--------------------------------------------------------------------------------
/Ch10/stage_four/Ch10s4.test:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch10/stage_four/Ch10s4.test
--------------------------------------------------------------------------------
/Ch10/stage_four/ha_spartan.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan Storage Engine Plugin
3 | */
4 |
5 | #include "my_global.h" /* ulonglong */
6 | #include "thr_lock.h" /* THR_LOCK, THR_LOCK_DATA */
7 | #include "handler.h" /* handler */
8 | #include "spartan_data.h"
9 |
10 | class Spartan_share : public Handler_share {
11 | public:
12 | mysql_mutex_t mutex;
13 | THR_LOCK lock;
14 | Spartan_data *data_class;
15 | Spartan_share();
16 | ~Spartan_share()
17 | {
18 | thr_lock_delete(&lock);
19 | mysql_mutex_destroy(&mutex);
20 | if (data_class != NULL)
21 | delete data_class;
22 | data_class = NULL;
23 | }
24 | };
25 |
26 | /*
27 | Class definition for the storage engine
28 | */
29 | class ha_spartan: public handler
30 | {
31 | THR_LOCK_DATA lock; /* MySQL lock */
32 | Spartan_share *share; ///< Shared lock info
33 | Spartan_share *get_share(); ///< Get the share
34 | off_t current_position; /* Current position in the file during a file scan */
35 |
36 | public:
37 | ha_spartan(handlerton *hton, TABLE_SHARE *table_ar);
38 | ~ha_spartan()
39 | {
40 | }
41 | /* The name that will be used for display purposes */
42 | const char *table_type() const { return "SPARTAN"; }
43 | /*
44 | The name of the index type that will be used for display
45 | don't implement this method unless you really have indexes
46 | */
47 | const char *index_type(uint inx) { return "HASH"; }
48 | /*
49 | The file extensions.
50 | */
51 | const char **bas_ext() const;
52 | /*
53 | This is a list of flags that says what the storage engine
54 | implements. The current table flags are documented in
55 | handler.h
56 | */
57 | ulonglong table_flags() const
58 | {
59 | return HA_BINLOG_STMT_CAPABLE;
60 | }
61 | /*
62 | This is a bitmap of flags that says how the storage engine
63 | implements indexes. The current index flags are documented in
64 | handler.h. If you do not implement indexes, just return zero
65 | here.
66 |
67 | part is the key part to check. First key part is 0
68 | If all_parts it's set, MySQL want to know the flags for the combined
69 | index up to and including 'part'.
70 | */
71 | ulong index_flags(uint inx, uint part, bool all_parts) const
72 | {
73 | return 0;
74 | }
75 | /*
76 | unireg.cc will call the following to make sure that the storage engine can
77 | handle the data it is about to send.
78 |
79 | Return *real* limits of your storage engine here. MySQL will do
80 | min(your_limits, MySQL_limits) automatically
81 |
82 | There is no need to implement ..._key_... methods if you don't suport
83 | indexes.
84 | */
85 | uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
86 | uint max_supported_keys() const { return 0; }
87 | uint max_supported_key_parts() const { return 0; }
88 | uint max_supported_key_length() const { return 0; }
89 | /*
90 | Called in test_quick_select to determine if indexes should be used.
91 | */
92 | virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
93 | /*
94 | The next method will never be called if you do not implement indexes.
95 | */
96 | virtual double read_time(uint, uint, ha_rows rows)
97 | { return (double) rows / 20.0+1; }
98 |
99 | /*
100 | Everything below are methods that we implment in ha_spartan.cc.
101 |
102 | Most of these methods are not obligatory, skip them and
103 | MySQL will treat them as not implemented
104 | */
105 | int open(const char *name, int mode, uint test_if_locked); // required
106 | int close(void); // required
107 |
108 | int write_row(uchar * buf);
109 | int update_row(const uchar * old_data, uchar * new_data);
110 | int delete_row(const uchar * buf);
111 | int index_read_map(uchar *buf, const uchar *key,
112 | key_part_map keypart_map, enum ha_rkey_function find_flag);
113 | int index_next(uchar * buf);
114 | int index_prev(uchar * buf);
115 | int index_first(uchar * buf);
116 | int index_last(uchar * buf);
117 | /*
118 | unlike index_init(), rnd_init() can be called two times
119 | without rnd_end() in between (it only makes sense if scan=1).
120 | then the second call should prepare for the new table scan
121 | (e.g if rnd_init allocates the cursor, second call should
122 | position it to the start of the table, no need to deallocate
123 | and allocate it again
124 | */
125 | int rnd_init(bool scan); //required
126 | int rnd_end();
127 | int rnd_next(uchar *buf); //required
128 | int rnd_pos(uchar * buf, uchar *pos); //required
129 | void position(const uchar *record); //required
130 | int info(uint); //required
131 |
132 | int extra(enum ha_extra_function operation);
133 | int external_lock(THD *thd, int lock_type); //required
134 | int delete_all_rows(void);
135 | int truncate();
136 | ha_rows records_in_range(uint inx, key_range *min_key,
137 | key_range *max_key);
138 | int delete_table(const char *from);
139 | int rename_table(const char * from, const char * to);
140 | int create(const char *name, TABLE *form,
141 | HA_CREATE_INFO *create_info); //required
142 |
143 | THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
144 | enum thr_lock_type lock_type); //required
145 | };
146 |
147 |
--------------------------------------------------------------------------------
/Ch10/stage_four/spartan_data.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan_data.h
3 |
4 | This header defines a simple data file class for reading raw data to and
5 | from disk. The data written is in byte format so it can be anything you
6 | want it to be. The write_row and read_row accept the length of the data
7 | item to be read.
8 | */
9 | #include "my_global.h"
10 | #include "my_sys.h"
11 |
12 | class Spartan_data
13 | {
14 | public:
15 | Spartan_data(void);
16 | ~Spartan_data(void);
17 | int create_table(char *path);
18 | int open_table(char *path);
19 | long long write_row(uchar *buf, int length);
20 | long long update_row(uchar *old_rec, uchar *new_rec,
21 | int length, long long position);
22 | int read_row(uchar *buf, int length, long long position);
23 | int delete_row(uchar *old_rec, int length, long long position);
24 | int close_table();
25 | long long cur_position();
26 | int records();
27 | int del_records();
28 | int trunc_table();
29 | int row_size(int length);
30 | private:
31 | File data_file;
32 | int header_size;
33 | int record_header_size;
34 | bool crashed;
35 | int number_records;
36 | int number_del_records;
37 | int read_header();
38 | int write_header();
39 | };
40 |
--------------------------------------------------------------------------------
/Ch10/stage_one/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Spartan storage engine plugin
2 |
3 | SET(SPARTAN_PLUGIN_STATIC "spartan")
4 | SET(SPARTAN_PLUGIN_DYNAMIC "spartan")
5 |
6 | SET(SPARTAN_SOURCES ha_spartan.cc ha_spartan.h spartan_data.cc spartan_data.h)
7 | MYSQL_ADD_PLUGIN(spartan ${SPARTAN_SOURCES} STORAGE_ENGINE MODULE_ONLY)
8 |
--------------------------------------------------------------------------------
/Ch10/stage_one/Ch10s1.test:
--------------------------------------------------------------------------------
1 | #
2 | # Simple test for the Spartan storage engine
3 | #
4 | --disable_warnings
5 | drop table if exists t1;
6 | --enable_warnings
7 |
8 | CREATE TABLE t1 (
9 | col_a int,
10 | col_b varchar(20),
11 | col_c int
12 | ) ENGINE=SPARTAN;
13 |
14 | SELECT * FROM t1;
15 |
16 | DROP TABLE t1;
17 |
--------------------------------------------------------------------------------
/Ch10/stage_one/ha_spartan.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan Storage Engine Plugin
3 | */
4 |
5 | #include "my_global.h" /* ulonglong */
6 | #include "thr_lock.h" /* THR_LOCK, THR_LOCK_DATA */
7 | #include "handler.h" /* handler */
8 | #include "spartan_data.h"
9 |
10 | class Spartan_share : public Handler_share {
11 | public:
12 | mysql_mutex_t mutex;
13 | THR_LOCK lock;
14 | Spartan_share();
15 | ~Spartan_share()
16 | {
17 | thr_lock_delete(&lock);
18 | mysql_mutex_destroy(&mutex);
19 | }
20 | };
21 |
22 | /*
23 | Class definition for the storage engine
24 | */
25 | class ha_spartan: public handler
26 | {
27 | THR_LOCK_DATA lock; /* MySQL lock */
28 | Spartan_share *share; ///< Shared lock info
29 | Spartan_share *get_share(); ///< Get the share
30 |
31 | public:
32 | ha_spartan(handlerton *hton, TABLE_SHARE *table_ar);
33 | ~ha_spartan()
34 | {
35 | }
36 | /* The name that will be used for display purposes */
37 | const char *table_type() const { return "SPARTAN"; }
38 | /*
39 | The name of the index type that will be used for display
40 | don't implement this method unless you really have indexes
41 | */
42 | const char *index_type(uint inx) { return "HASH"; }
43 | /*
44 | The file extensions.
45 | */
46 | const char **bas_ext() const;
47 | /*
48 | This is a list of flags that says what the storage engine
49 | implements. The current table flags are documented in
50 | handler.h
51 | */
52 | ulonglong table_flags() const
53 | {
54 | return HA_BINLOG_STMT_CAPABLE;
55 | }
56 | /*
57 | This is a bitmap of flags that says how the storage engine
58 | implements indexes. The current index flags are documented in
59 | handler.h. If you do not implement indexes, just return zero
60 | here.
61 |
62 | part is the key part to check. First key part is 0
63 | If all_parts it's set, MySQL want to know the flags for the combined
64 | index up to and including 'part'.
65 | */
66 | ulong index_flags(uint inx, uint part, bool all_parts) const
67 | {
68 | return 0;
69 | }
70 | /*
71 | unireg.cc will call the following to make sure that the storage engine can
72 | handle the data it is about to send.
73 |
74 | Return *real* limits of your storage engine here. MySQL will do
75 | min(your_limits, MySQL_limits) automatically
76 |
77 | There is no need to implement ..._key_... methods if you don't suport
78 | indexes.
79 | */
80 | uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
81 | uint max_supported_keys() const { return 0; }
82 | uint max_supported_key_parts() const { return 0; }
83 | uint max_supported_key_length() const { return 0; }
84 | /*
85 | Called in test_quick_select to determine if indexes should be used.
86 | */
87 | virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
88 | /*
89 | The next method will never be called if you do not implement indexes.
90 | */
91 | virtual double read_time(uint, uint, ha_rows rows)
92 | { return (double) rows / 20.0+1; }
93 |
94 | /*
95 | Everything below are methods that we implment in ha_spartan.cc.
96 |
97 | Most of these methods are not obligatory, skip them and
98 | MySQL will treat them as not implemented
99 | */
100 | int open(const char *name, int mode, uint test_if_locked); // required
101 | int close(void); // required
102 |
103 | int write_row(uchar * buf);
104 | int update_row(const uchar * old_data, uchar * new_data);
105 | int delete_row(const uchar * buf);
106 | int index_read_map(uchar *buf, const uchar *key,
107 | key_part_map keypart_map, enum ha_rkey_function find_flag);
108 | int index_next(uchar * buf);
109 | int index_prev(uchar * buf);
110 | int index_first(uchar * buf);
111 | int index_last(uchar * buf);
112 | /*
113 | unlike index_init(), rnd_init() can be called two times
114 | without rnd_end() in between (it only makes sense if scan=1).
115 | then the second call should prepare for the new table scan
116 | (e.g if rnd_init allocates the cursor, second call should
117 | position it to the start of the table, no need to deallocate
118 | and allocate it again
119 | */
120 | int rnd_init(bool scan); //required
121 | int rnd_end();
122 | int rnd_next(uchar *buf); //required
123 | int rnd_pos(uchar * buf, uchar *pos); //required
124 | void position(const uchar *record); //required
125 | int info(uint); //required
126 |
127 | int extra(enum ha_extra_function operation);
128 | int external_lock(THD *thd, int lock_type); //required
129 | int delete_all_rows(void);
130 | int truncate();
131 | ha_rows records_in_range(uint inx, key_range *min_key,
132 | key_range *max_key);
133 | int delete_table(const char *from);
134 | int rename_table(const char * from, const char * to);
135 | int create(const char *name, TABLE *form,
136 | HA_CREATE_INFO *create_info); //required
137 |
138 | THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
139 | enum thr_lock_type lock_type); //required
140 | };
141 |
142 |
--------------------------------------------------------------------------------
/Ch10/stage_one/spartan_data.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan_data.h
3 |
4 | This header defines a simple data file class for reading raw data to and
5 | from disk. The data written is in byte format so it can be anything you
6 | want it to be. The write_row and read_row accept the length of the data
7 | item to be read.
8 | */
9 | #include "my_global.h"
10 | #include "my_sys.h"
11 |
12 | class Spartan_data
13 | {
14 | public:
15 | Spartan_data(void);
16 | ~Spartan_data(void);
17 | int create_table(char *path);
18 | int open_table(char *path);
19 | long long write_row(uchar *buf, int length);
20 | long long update_row(uchar *old_rec, uchar *new_rec,
21 | int length, long long position);
22 | int read_row(uchar *buf, int length, long long position);
23 | int delete_row(uchar *old_rec, int length, long long position);
24 | int close_table();
25 | long long cur_position();
26 | int records();
27 | int del_records();
28 | int trunc_table();
29 | int row_size(int length);
30 | private:
31 | File data_file;
32 | int header_size;
33 | int record_header_size;
34 | bool crashed;
35 | int number_records;
36 | int number_del_records;
37 | int read_header();
38 | int write_header();
39 | };
40 |
--------------------------------------------------------------------------------
/Ch10/stage_three/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Spartan storage engine plugin
2 |
3 | SET(SPARTAN_PLUGIN_STATIC "spartan")
4 | SET(SPARTAN_PLUGIN_DYNAMIC "spartan")
5 |
6 | SET(SPARTAN_SOURCES ha_spartan.cc ha_spartan.h spartan_data.cc spartan_data.h)
7 |
8 | MYSQL_ADD_PLUGIN(spartan ${SPARTAN_SOURCES} STORAGE_ENGINE MODULE_ONLY)
9 |
10 | TARGET_LINK_LIBRARIES(spartan mysys)
11 |
--------------------------------------------------------------------------------
/Ch10/stage_three/Ch10s3.test:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch10/stage_three/Ch10s3.test
--------------------------------------------------------------------------------
/Ch10/stage_three/ha_spartan.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan Storage Engine Plugin
3 | */
4 |
5 | #include "my_global.h" /* ulonglong */
6 | #include "thr_lock.h" /* THR_LOCK, THR_LOCK_DATA */
7 | #include "handler.h" /* handler */
8 | #include "spartan_data.h"
9 |
10 | class Spartan_share : public Handler_share {
11 | public:
12 | mysql_mutex_t mutex;
13 | THR_LOCK lock;
14 | Spartan_data *data_class;
15 | Spartan_share();
16 | ~Spartan_share()
17 | {
18 | thr_lock_delete(&lock);
19 | mysql_mutex_destroy(&mutex);
20 | if (data_class != NULL)
21 | delete data_class;
22 | data_class = NULL;
23 | }
24 | };
25 |
26 | /*
27 | Class definition for the storage engine
28 | */
29 | class ha_spartan: public handler
30 | {
31 | THR_LOCK_DATA lock; /* MySQL lock */
32 | Spartan_share *share; ///< Shared lock info
33 | Spartan_share *get_share(); ///< Get the share
34 | off_t current_position; /* Current position in the file during a file scan */
35 |
36 | public:
37 | ha_spartan(handlerton *hton, TABLE_SHARE *table_ar);
38 | ~ha_spartan()
39 | {
40 | }
41 | /* The name that will be used for display purposes */
42 | const char *table_type() const { return "SPARTAN"; }
43 | /*
44 | The name of the index type that will be used for display
45 | don't implement this method unless you really have indexes
46 | */
47 | const char *index_type(uint inx) { return "HASH"; }
48 | /*
49 | The file extensions.
50 | */
51 | const char **bas_ext() const;
52 | /*
53 | This is a list of flags that says what the storage engine
54 | implements. The current table flags are documented in
55 | handler.h
56 | */
57 | ulonglong table_flags() const
58 | {
59 | return HA_BINLOG_STMT_CAPABLE;
60 | }
61 | /*
62 | This is a bitmap of flags that says how the storage engine
63 | implements indexes. The current index flags are documented in
64 | handler.h. If you do not implement indexes, just return zero
65 | here.
66 |
67 | part is the key part to check. First key part is 0
68 | If all_parts it's set, MySQL want to know the flags for the combined
69 | index up to and including 'part'.
70 | */
71 | ulong index_flags(uint inx, uint part, bool all_parts) const
72 | {
73 | return 0;
74 | }
75 | /*
76 | unireg.cc will call the following to make sure that the storage engine can
77 | handle the data it is about to send.
78 |
79 | Return *real* limits of your storage engine here. MySQL will do
80 | min(your_limits, MySQL_limits) automatically
81 |
82 | There is no need to implement ..._key_... methods if you don't suport
83 | indexes.
84 | */
85 | uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
86 | uint max_supported_keys() const { return 0; }
87 | uint max_supported_key_parts() const { return 0; }
88 | uint max_supported_key_length() const { return 0; }
89 | /*
90 | Called in test_quick_select to determine if indexes should be used.
91 | */
92 | virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
93 | /*
94 | The next method will never be called if you do not implement indexes.
95 | */
96 | virtual double read_time(uint, uint, ha_rows rows)
97 | { return (double) rows / 20.0+1; }
98 |
99 | /*
100 | Everything below are methods that we implment in ha_spartan.cc.
101 |
102 | Most of these methods are not obligatory, skip them and
103 | MySQL will treat them as not implemented
104 | */
105 | int open(const char *name, int mode, uint test_if_locked); // required
106 | int close(void); // required
107 |
108 | int write_row(uchar * buf);
109 | int update_row(const uchar * old_data, uchar * new_data);
110 | int delete_row(const uchar * buf);
111 | int index_read_map(uchar *buf, const uchar *key,
112 | key_part_map keypart_map, enum ha_rkey_function find_flag);
113 | int index_next(uchar * buf);
114 | int index_prev(uchar * buf);
115 | int index_first(uchar * buf);
116 | int index_last(uchar * buf);
117 | /*
118 | unlike index_init(), rnd_init() can be called two times
119 | without rnd_end() in between (it only makes sense if scan=1).
120 | then the second call should prepare for the new table scan
121 | (e.g if rnd_init allocates the cursor, second call should
122 | position it to the start of the table, no need to deallocate
123 | and allocate it again
124 | */
125 | int rnd_init(bool scan); //required
126 | int rnd_end();
127 | int rnd_next(uchar *buf); //required
128 | int rnd_pos(uchar * buf, uchar *pos); //required
129 | void position(const uchar *record); //required
130 | int info(uint); //required
131 |
132 | int extra(enum ha_extra_function operation);
133 | int external_lock(THD *thd, int lock_type); //required
134 | int delete_all_rows(void);
135 | int truncate();
136 | ha_rows records_in_range(uint inx, key_range *min_key,
137 | key_range *max_key);
138 | int delete_table(const char *from);
139 | int rename_table(const char * from, const char * to);
140 | int create(const char *name, TABLE *form,
141 | HA_CREATE_INFO *create_info); //required
142 |
143 | THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
144 | enum thr_lock_type lock_type); //required
145 | };
146 |
147 |
--------------------------------------------------------------------------------
/Ch10/stage_three/spartan_data.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan_data.h
3 |
4 | This header defines a simple data file class for reading raw data to and
5 | from disk. The data written is in byte format so it can be anything you
6 | want it to be. The write_row and read_row accept the length of the data
7 | item to be read.
8 | */
9 | #include "my_global.h"
10 | #include "my_sys.h"
11 |
12 | class Spartan_data
13 | {
14 | public:
15 | Spartan_data(void);
16 | ~Spartan_data(void);
17 | int create_table(char *path);
18 | int open_table(char *path);
19 | long long write_row(uchar *buf, int length);
20 | long long update_row(uchar *old_rec, uchar *new_rec,
21 | int length, long long position);
22 | int read_row(uchar *buf, int length, long long position);
23 | int delete_row(uchar *old_rec, int length, long long position);
24 | int close_table();
25 | long long cur_position();
26 | int records();
27 | int del_records();
28 | int trunc_table();
29 | int row_size(int length);
30 | private:
31 | File data_file;
32 | int header_size;
33 | int record_header_size;
34 | bool crashed;
35 | int number_records;
36 | int number_del_records;
37 | int read_header();
38 | int write_header();
39 | };
40 |
--------------------------------------------------------------------------------
/Ch10/stage_two/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # Spartan storage engine plugin
2 |
3 | SET(SPARTAN_PLUGIN_STATIC "spartan")
4 | SET(SPARTAN_PLUGIN_DYNAMIC "spartan")
5 |
6 | SET(SPARTAN_SOURCES ha_spartan.cc ha_spartan.h spartan_data.cc spartan_data.h)
7 |
8 | MYSQL_ADD_PLUGIN(spartan ${SPARTAN_SOURCES} STORAGE_ENGINE MODULE_ONLY)
9 |
10 | TARGET_LINK_LIBRARIES(spartan mysys)
11 |
--------------------------------------------------------------------------------
/Ch10/stage_two/Ch10s2.test:
--------------------------------------------------------------------------------
1 | #
2 | # Simple test for the Spartan storage engine
3 | #
4 | --disable_warnings
5 | drop table if exists t1;
6 | --enable_warnings
7 |
8 | CREATE TABLE t1 (
9 | col_a int,
10 | col_b varchar(20),
11 | col_c int
12 | ) ENGINE=SPARTAN;
13 |
14 | SELECT * FROM t1;
15 |
16 | RENAME TABLE t1 TO t2;
17 |
18 | DROP TABLE t2;
19 |
--------------------------------------------------------------------------------
/Ch10/stage_two/ha_spartan.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan Storage Engine Plugin
3 | */
4 |
5 | #include "my_global.h" /* ulonglong */
6 | #include "thr_lock.h" /* THR_LOCK, THR_LOCK_DATA */
7 | #include "handler.h" /* handler */
8 | #include "spartan_data.h"
9 |
10 | class Spartan_share : public Handler_share {
11 | public:
12 | mysql_mutex_t mutex;
13 | THR_LOCK lock;
14 | Spartan_data *data_class;
15 | Spartan_share();
16 | ~Spartan_share()
17 | {
18 | thr_lock_delete(&lock);
19 | mysql_mutex_destroy(&mutex);
20 | if (data_class != NULL)
21 | delete data_class;
22 | data_class = NULL;
23 | }
24 | };
25 |
26 | /*
27 | Class definition for the storage engine
28 | */
29 | class ha_spartan: public handler
30 | {
31 | THR_LOCK_DATA lock; /* MySQL lock */
32 | Spartan_share *share; ///< Shared lock info
33 | Spartan_share *get_share(); ///< Get the share
34 |
35 | public:
36 | ha_spartan(handlerton *hton, TABLE_SHARE *table_ar);
37 | ~ha_spartan()
38 | {
39 | }
40 | /* The name that will be used for display purposes */
41 | const char *table_type() const { return "SPARTAN"; }
42 | /*
43 | The name of the index type that will be used for display
44 | don't implement this method unless you really have indexes
45 | */
46 | const char *index_type(uint inx) { return "HASH"; }
47 | /*
48 | The file extensions.
49 | */
50 | const char **bas_ext() const;
51 | /*
52 | This is a list of flags that says what the storage engine
53 | implements. The current table flags are documented in
54 | handler.h
55 | */
56 | ulonglong table_flags() const
57 | {
58 | return HA_BINLOG_STMT_CAPABLE;
59 | }
60 | /*
61 | This is a bitmap of flags that says how the storage engine
62 | implements indexes. The current index flags are documented in
63 | handler.h. If you do not implement indexes, just return zero
64 | here.
65 |
66 | part is the key part to check. First key part is 0
67 | If all_parts it's set, MySQL want to know the flags for the combined
68 | index up to and including 'part'.
69 | */
70 | ulong index_flags(uint inx, uint part, bool all_parts) const
71 | {
72 | return 0;
73 | }
74 | /*
75 | unireg.cc will call the following to make sure that the storage engine can
76 | handle the data it is about to send.
77 |
78 | Return *real* limits of your storage engine here. MySQL will do
79 | min(your_limits, MySQL_limits) automatically
80 |
81 | There is no need to implement ..._key_... methods if you don't suport
82 | indexes.
83 | */
84 | uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
85 | uint max_supported_keys() const { return 0; }
86 | uint max_supported_key_parts() const { return 0; }
87 | uint max_supported_key_length() const { return 0; }
88 | /*
89 | Called in test_quick_select to determine if indexes should be used.
90 | */
91 | virtual double scan_time() { return (double) (stats.records+stats.deleted) / 20.0+10; }
92 | /*
93 | The next method will never be called if you do not implement indexes.
94 | */
95 | virtual double read_time(uint, uint, ha_rows rows)
96 | { return (double) rows / 20.0+1; }
97 |
98 | /*
99 | Everything below are methods that we implment in ha_spartan.cc.
100 |
101 | Most of these methods are not obligatory, skip them and
102 | MySQL will treat them as not implemented
103 | */
104 | int open(const char *name, int mode, uint test_if_locked); // required
105 | int close(void); // required
106 |
107 | int write_row(uchar * buf);
108 | int update_row(const uchar * old_data, uchar * new_data);
109 | int delete_row(const uchar * buf);
110 | int index_read_map(uchar *buf, const uchar *key,
111 | key_part_map keypart_map, enum ha_rkey_function find_flag);
112 | int index_next(uchar * buf);
113 | int index_prev(uchar * buf);
114 | int index_first(uchar * buf);
115 | int index_last(uchar * buf);
116 | /*
117 | unlike index_init(), rnd_init() can be called two times
118 | without rnd_end() in between (it only makes sense if scan=1).
119 | then the second call should prepare for the new table scan
120 | (e.g if rnd_init allocates the cursor, second call should
121 | position it to the start of the table, no need to deallocate
122 | and allocate it again
123 | */
124 | int rnd_init(bool scan); //required
125 | int rnd_end();
126 | int rnd_next(uchar *buf); //required
127 | int rnd_pos(uchar * buf, uchar *pos); //required
128 | void position(const uchar *record); //required
129 | int info(uint); //required
130 |
131 | int extra(enum ha_extra_function operation);
132 | int external_lock(THD *thd, int lock_type); //required
133 | int delete_all_rows(void);
134 | int truncate();
135 | ha_rows records_in_range(uint inx, key_range *min_key,
136 | key_range *max_key);
137 | int delete_table(const char *from);
138 | int rename_table(const char * from, const char * to);
139 | int create(const char *name, TABLE *form,
140 | HA_CREATE_INFO *create_info); //required
141 |
142 | THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
143 | enum thr_lock_type lock_type); //required
144 | };
145 |
146 |
--------------------------------------------------------------------------------
/Ch10/stage_two/spartan_data.h:
--------------------------------------------------------------------------------
1 | /*
2 | Spartan_data.h
3 |
4 | This header defines a simple data file class for reading raw data to and
5 | from disk. The data written is in byte format so it can be anything you
6 | want it to be. The write_row and read_row accept the length of the data
7 | item to be read.
8 | */
9 | #include "my_global.h"
10 | #include "my_sys.h"
11 |
12 | class Spartan_data
13 | {
14 | public:
15 | Spartan_data(void);
16 | ~Spartan_data(void);
17 | int create_table(char *path);
18 | int open_table(char *path);
19 | long long write_row(uchar *buf, int length);
20 | long long update_row(uchar *old_rec, uchar *new_rec,
21 | int length, long long position);
22 | int read_row(uchar *buf, int length, long long position);
23 | int delete_row(uchar *old_rec, int length, long long position);
24 | int close_table();
25 | long long cur_position();
26 | int records();
27 | int del_records();
28 | int trunc_table();
29 | int row_size(int length);
30 | private:
31 | File data_file;
32 | int header_size;
33 | int record_header_size;
34 | bool crashed;
35 | int number_records;
36 | int number_del_records;
37 | int read_header();
38 | int write_header();
39 | };
40 |
--------------------------------------------------------------------------------
/Ch12/ch12.diff:
--------------------------------------------------------------------------------
1 | === modified file 'sql/CMakeLists.txt'
2 | --- sql/CMakeLists.txt 2012-08-07 05:14:58 +0000
3 | +++ sql/CMakeLists.txt 2012-09-16 18:05:38 +0000
4 | @@ -132,6 +132,8 @@ SET(SQL_SHARED_SOURCES
5 | sql_manager.cc
6 | sql_optimizer.cc
7 | sql_parse.cc
8 | + sql_dbxp_parse.cc
9 | + query_tree.cc
10 | sql_partition.cc
11 | sql_partition_admin.cc
12 | sql_planner.cc
13 |
14 | === modified file 'sql/lex.h'
15 | --- sql/lex.h 2012-09-11 17:35:40 +0000
16 | +++ sql/lex.h 2012-09-16 18:01:41 +0000
17 | @@ -160,6 +160,11 @@ static SYMBOL symbols[] = {
18 | { "DAY_MICROSECOND", SYM(DAY_MICROSECOND_SYM)},
19 | { "DAY_MINUTE", SYM(DAY_MINUTE_SYM)},
20 | { "DAY_SECOND", SYM(DAY_SECOND_SYM)},
21 | +/* BEGIN DBXP MODIFICATION */
22 | +/* Reason for Modification: */
23 | +/* This section identifies the symbols and values for the DBXP token */
24 | + { "DBXP_SELECT", SYM(DBXP_SELECT_SYM)},
25 | +/* END DBXP MODIFICATION */
26 | { "DEALLOCATE", SYM(DEALLOCATE_SYM)},
27 | { "DEC", SYM(DECIMAL_SYM)},
28 | { "DECIMAL", SYM(DECIMAL_SYM)},
29 |
30 | === modified file 'sql/mysqld.cc'
31 | --- sql/mysqld.cc 2012-09-11 17:35:40 +0000
32 | +++ sql/mysqld.cc 2012-09-16 18:01:41 +0000
33 | @@ -3699,8 +3699,8 @@ int init_common_variables()
34 | the array, excluding the last element - terminator) must match the number
35 | of SQLCOM_ constants.
36 | */
37 | - compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
38 | - SQLCOM_END + 8);
39 | + //compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 ==
40 | + // SQLCOM_END + 8);
41 | #endif
42 |
43 | if (get_options(&remaining_argc, &remaining_argv))
44 | @@ -8671,6 +8671,11 @@ static void set_server_version(void)
45 | #endif
46 | if (opt_log || opt_slow_log || opt_bin_log)
47 | strmov(end, "-log"); // This may slow down system
48 | +/* BEGIN DBXP MODIFICATION */
49 | +/* Reason for Modification: */
50 | +/* This section adds the DBXP version number to the MySQL version number. */
51 | + strmov(end, "-DBXP 2.0");
52 | +/* END DBXP MODIFICATION */
53 | }
54 |
55 |
56 |
57 | === modified file 'sql/sql_cmd.h'
58 | --- sql/sql_cmd.h 2012-09-11 17:35:40 +0000
59 | +++ sql/sql_cmd.h 2012-09-16 18:01:41 +0000
60 | @@ -43,6 +43,13 @@ enum enum_sql_command {
61 | SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
62 | SQLCOM_SHOW_TRIGGERS,
63 |
64 | +/* BEGIN DBXP MODIFICATION */
65 | +/* Reason for Modification: */
66 | +/* This section captures the enumerations for the DBXP command tokens */
67 | + SQLCOM_DBXP_SELECT,
68 | + SQLCOM_DBXP_EXPLAIN_SELECT,
69 | +/* END DBXP MODIFICATION */
70 | +
71 | SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
72 | SQLCOM_GRANT,
73 | SQLCOM_CHANGE_DB, SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_ALTER_DB,
74 |
75 | === modified file 'sql/sql_parse.cc'
76 | --- sql/sql_parse.cc 2012-09-11 17:35:40 +0000
77 | +++ sql/sql_parse.cc 2012-09-16 18:01:41 +0000
78 | @@ -2197,6 +2197,13 @@ err:
79 | }
80 |
81 |
82 | +/* BEGIN DBXP MODIFICATION */
83 | +/* Reason for Modification: */
84 | +/* This section adds the code to call the new SELECT DBXP command. */
85 | +int DBXP_select_command(THD *thd);
86 | +int DBXP_explain_select_command(THD *thd);
87 | +/* END DBXP MODIFICATION */
88 | +
89 | /**
90 | Execute command saved in thd and lex->sql_command.
91 |
92 | @@ -2552,6 +2559,20 @@ mysql_execute_command(THD *thd)
93 | res= execute_sqlcom_select(thd, all_tables);
94 | break;
95 | }
96 | +/* BEGIN DBXP MODIFICATION */
97 | +/* Reason for Modification: */
98 | +/* This section adds the code to call the new SELECT DBXP command. */
99 | + case SQLCOM_DBXP_SELECT:
100 | + {
101 | + DBXP_select_command(thd);
102 | + break;
103 | + }
104 | + case SQLCOM_DBXP_EXPLAIN_SELECT:
105 | + {
106 | + DBXP_explain_select_command(thd);
107 | + break;
108 | + }
109 | +/* END DBXP MODIFICATION */
110 | case SQLCOM_PREPARE:
111 | {
112 | mysql_sql_stmt_prepare(thd);
113 |
114 | === modified file 'sql/sql_yacc.yy'
115 | --- sql/sql_yacc.yy 2012-09-11 17:35:40 +0000
116 | +++ sql/sql_yacc.yy 2012-09-16 18:01:41 +0000
117 | @@ -1124,6 +1124,11 @@ bool my_yyoverflow(short **a, YYSTYPE **
118 | %token DAY_MINUTE_SYM
119 | %token DAY_SECOND_SYM
120 | %token DAY_SYM /* SQL-2003-R */
121 | +/* BEGIN DBXP MODIFICATION */
122 | +/* Reason for Modification: */
123 | +/* This section defines the tokens for the DBXP commands */
124 | +%token DBXP_SELECT_SYM
125 | +/* END DBXP MODIFICATION */
126 | %token DEALLOCATE_SYM /* SQL-2003-R */
127 | %token DECIMAL_NUM
128 | %token DECIMAL_SYM /* SQL-2003-R */
129 | @@ -1801,7 +1806,11 @@ bool my_yyoverflow(short **a, YYSTYPE **
130 | %type comp_op
131 |
132 | %type
133 | - query verb_clause create change select do drop insert replace insert2
134 | +/* BEGIN DBXP MODIFICATION */
135 | +/* Reason for Modification: */
136 | +/* Add the dbxp_select statement to the NONE type definition. */
137 | + query verb_clause create change select dbxp_select do drop insert replace insert2
138 | +/* END DBXP MODIFICATION */
139 | insert_values update delete truncate rename
140 | show describe load alter optimize keycache preload flush
141 | reset purge begin commit rollback savepoint release
142 | @@ -2019,6 +2028,11 @@ statement:
143 | | rollback
144 | | savepoint
145 | | select
146 | +/* BEGIN DBXP MODIFICATION */
147 | +/* Reason for Modification: */
148 | +/* Add the dbxp_select statement to the list of statements(commands). */
149 | + | dbxp_select
150 | +/* END DBXP MODIFICATION */
151 | | set
152 | | signal_stmt
153 | | show
154 | @@ -8514,14 +8528,76 @@ opt_ignore_leaves:
155 | */
156 |
157 |
158 | +/* BEGIN DBXP MODIFICATION */
159 | +/* Reason for Modification: */
160 | +/* This section captures (parses) the SELECT DBXP statement */
161 | +
162 | +dbxp_select:
163 | + DBXP_SELECT_SYM DBXP_select_options DBXP_select_item_list
164 | + DBXP_select_from
165 | + {
166 | + LEX *lex= Lex;
167 | + lex->sql_command = SQLCOM_DBXP_SELECT;
168 | + }
169 | + ;
170 | +
171 | +/* END DBXP MODIFICATION */
172 | +
173 | select:
174 | - select_init
175 | + select_init
176 | {
177 | LEX *lex= Lex;
178 | lex->sql_command= SQLCOM_SELECT;
179 | }
180 | ;
181 |
182 | +/* BEGIN DBXP MODIFICATION */
183 | +/* Reason for Modification: */
184 | +/* This section captures (parses) the sub parts of the SELECT DBXP statement */
185 | +
186 | +DBXP_select_options:
187 | + /* empty */
188 | + | DISTINCT
189 | + {
190 | + Select->options|= SELECT_DISTINCT;
191 | + }
192 | + ;
193 | +
194 | +DBXP_select_from:
195 | + FROM join_table_list DBXP_where_clause {};
196 | +
197 | +DBXP_select_item_list:
198 | + /* empty */
199 | + | DBXP_select_item_list ',' select_item
200 | + | select_item
201 | + | '*'
202 | + {
203 | + THD *thd= YYTHD;
204 | + Item *item= new (thd->mem_root)
205 | + Item_field(&thd->lex->current_select->context,
206 | + NULL, NULL, "*");
207 | + if (item == NULL)
208 | + MYSQL_YYABORT;
209 | + if (add_item_to_list(thd, item))
210 | + MYSQL_YYABORT;
211 | + (thd->lex->current_select->with_wild)++;
212 | + };
213 | +
214 | +DBXP_where_clause:
215 | + /* empty */ { Select->where= 0; }
216 | + | WHERE expr
217 | + {
218 | + SELECT_LEX *select= Select;
219 | + select->where= $2;
220 | + if ($2)
221 | + $2->top_level_item();
222 | + }
223 | + ;
224 | +
225 | +
226 | +/* END DBXP MODIFICATION */
227 | +
228 | +
229 | /* Need select_init2 for subselects. */
230 | select_init:
231 | SELECT_SYM select_init2
232 | @@ -12631,7 +12707,21 @@ wild_and_where:
233 |
234 | /* A Oracle compatible synonym for show */
235 | describe:
236 | - describe_command table_ident
237 | +/* BEGIN DBXP MODIFICATION */
238 | +/* Reason for Modification: */
239 | +/* This section captures (parses) the EXPLAIN (DESCRIBE) DBXP statements */
240 | +
241 | + describe_command DBXP_SELECT_SYM DBXP_select_options DBXP_select_item_list
242 | + DBXP_select_from
243 | + {
244 | + LEX *lex= Lex;
245 | + lex->sql_command = SQLCOM_DBXP_EXPLAIN_SELECT;
246 | + lex->select_lex.db= 0;
247 | + lex->verbose= 0;
248 | + }
249 | +
250 | +/* END DBXP MODIFICATION */
251 | + | describe_command table_ident
252 | {
253 | LEX *lex= Lex;
254 | mysql_init_select(lex);
255 |
256 |
--------------------------------------------------------------------------------
/Ch12/ch12.sql:
--------------------------------------------------------------------------------
1 | # Source on localhost: ... connected.
2 | # Exporting metadata from expert_mysql
3 | DROP DATABASE IF EXISTS expert_mysql;
4 | CREATE DATABASE expert_mysql;
5 | USE expert_mysql;
6 | # TABLE: expert_mysql.building
7 | CREATE TABLE `building` (
8 | `dir_code` char(4) NOT NULL,
9 | `building` char(6) NOT NULL
10 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
11 | # TABLE: expert_mysql.directorate
12 | CREATE TABLE `directorate` (
13 | `dir_code` char(4) NOT NULL,
14 | `dir_name` char(30) DEFAULT NULL,
15 | `dir_head_id` char(9) DEFAULT NULL,
16 | PRIMARY KEY (`dir_code`)
17 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
18 | # TABLE: expert_mysql.staff
19 | CREATE TABLE `staff` (
20 | `id` char(9) NOT NULL,
21 | `first_name` char(20) DEFAULT NULL,
22 | `mid_name` char(20) DEFAULT NULL,
23 | `last_name` char(30) DEFAULT NULL,
24 | `sex` char(1) DEFAULT NULL,
25 | `salary` int(11) DEFAULT NULL,
26 | `mgr_id` char(9) DEFAULT NULL,
27 | PRIMARY KEY (`id`)
28 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
29 | # TABLE: expert_mysql.tasking
30 | CREATE TABLE `tasking` (
31 | `id` char(9) NOT NULL,
32 | `project_number` char(9) NOT NULL,
33 | `hours_worked` double DEFAULT NULL
34 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
35 | #...done.
36 | USE expert_mysql;
37 | # Exporting data from expert_mysql
38 | # Data for table expert_mysql.building:
39 | INSERT INTO expert_mysql.building VALUES ('N41', '1300');
40 | INSERT INTO expert_mysql.building VALUES ('N01', '1453');
41 | INSERT INTO expert_mysql.building VALUES ('M00', '1000');
42 | INSERT INTO expert_mysql.building VALUES ('N41', '1301');
43 | INSERT INTO expert_mysql.building VALUES ('N41', '1305');
44 | # Data for table expert_mysql.directorate:
45 | INSERT INTO expert_mysql.directorate VALUES ('N41', 'Development', '333445555');
46 | INSERT INTO expert_mysql.directorate VALUES ('N01', 'Human Resources', '123654321');
47 | INSERT INTO expert_mysql.directorate VALUES ('M00', 'Management', '333444444');
48 | # Data for table expert_mysql.staff:
49 | INSERT INTO expert_mysql.staff VALUES ('333445555', 'John', 'Q', 'Smith', 'M', 30000, '333444444');
50 | INSERT INTO expert_mysql.staff VALUES ('123763153', 'William', 'E', 'Walters', 'M', 25000, '123654321');
51 | INSERT INTO expert_mysql.staff VALUES ('333444444', 'Alicia', 'F', 'St.Cruz', 'F', 25000, 'None');
52 | INSERT INTO expert_mysql.staff VALUES ('921312388', 'Goy', 'X', 'Hong', 'F', 40000, '123654321');
53 | INSERT INTO expert_mysql.staff VALUES ('800122337', 'Rajesh', 'G', 'Kardakarna', 'M', 38000, '333445555');
54 | INSERT INTO expert_mysql.staff VALUES ('820123637', 'Monty', 'C', 'Smythe', 'M', 38000, '333445555');
55 | INSERT INTO expert_mysql.staff VALUES ('830132335', 'Richard', 'E', 'Jones', 'M', 38000, '333445555');
56 | INSERT INTO expert_mysql.staff VALUES ('333445665', 'Edward', 'E', 'Engles', 'M', 25000, '333445555');
57 | INSERT INTO expert_mysql.staff VALUES ('123654321', 'Beware', 'D', 'Borg', 'F', 55000, '333444444');
58 | INSERT INTO expert_mysql.staff VALUES ('123456789', 'Wilma', 'N', 'Maxima', 'F', 43000, '333445555');
59 | # Data for table expert_mysql.tasking:
60 | INSERT INTO expert_mysql.tasking VALUES ('333445555', '405', 23);
61 | INSERT INTO expert_mysql.tasking VALUES ('123763153', '405', 33.5);
62 | INSERT INTO expert_mysql.tasking VALUES ('921312388', '601', 44);
63 | INSERT INTO expert_mysql.tasking VALUES ('800122337', '300', 13);
64 | INSERT INTO expert_mysql.tasking VALUES ('820123637', '300', 9.5);
65 | INSERT INTO expert_mysql.tasking VALUES ('830132335', '401', 8.5);
66 | INSERT INTO expert_mysql.tasking VALUES ('333445555', '300', 11);
67 | INSERT INTO expert_mysql.tasking VALUES ('921312388', '500', 13);
68 | INSERT INTO expert_mysql.tasking VALUES ('800122337', '300', 44);
69 | INSERT INTO expert_mysql.tasking VALUES ('820123637', '401', 500.5);
70 | INSERT INTO expert_mysql.tasking VALUES ('830132335', '400', 12);
71 | INSERT INTO expert_mysql.tasking VALUES ('333445665', '600', 300.25);
72 | INSERT INTO expert_mysql.tasking VALUES ('123654321', '607', 444.75);
73 | INSERT INTO expert_mysql.tasking VALUES ('123456789', '300', 1000);
74 | #...done.
75 |
--------------------------------------------------------------------------------
/Ch12/ch12.test:
--------------------------------------------------------------------------------
1 | #
2 | # Sample test to test the DBXP_SELECT and EXPLAIN DBXP_SELECT commands
3 | #
4 |
5 | # Test 1: Test stubbed DBXP_SELECT command.
6 | DBXP_SELECT * FROM no_such_table;
7 |
8 | # Test 2: Test stubbed Query Tree implementation.
9 | DBXP_SELECT * FROM customer;
10 |
11 | # Test 3: Test stubbed EXPLAIN DBXP_SELECT command.
12 | EXPLAIN DBXP_SELECT * FROM customer;
13 |
--------------------------------------------------------------------------------
/Ch12/query_tree.cc:
--------------------------------------------------------------------------------
1 | /*
2 | query_tree.cc
3 |
4 | DESCRIPTION
5 | This file contains the Query_tree class. It is responsible for containing the
6 | internal representation of the query to be executed. It provides methods for
7 | optimizing and forming and inspecting the query tree. This class is the very
8 | heart of the DBXP query capability! It also provides the ability to store
9 | a binary "compiled" form of the query.
10 |
11 | NOTES
12 | The data structure is a binary tree that can have 0, 1, or 2 children. Only
13 | Join operations can have 2 children. All other operations have 0 or 1
14 | children. Each node in the tree is an operation and the links to children
15 | are the pipeline.
16 |
17 | SEE ALSO
18 | query_tree.h
19 | */
20 | #include "query_tree.h"
21 |
22 | Query_tree::query_node::query_node()
23 | {
24 | where_expr = NULL;
25 | join_expr = NULL;
26 | child = false;
27 | join_cond = Query_tree::jcUN;
28 | join_type = Query_tree::jnUNKNOWN;
29 | left = NULL;
30 | right = NULL;
31 | nodeid = -1;
32 | node_type = Query_tree::qntUndefined;
33 | sub_query = false;
34 | parent_nodeid = -1;
35 | }
36 |
37 |
38 | Query_tree::query_node::~query_node()
39 | {
40 | if(left)
41 | delete left;
42 | if(right)
43 | delete right;
44 | }
45 |
46 | Query_tree::~Query_tree(void)
47 | {
48 | if(root)
49 | delete root;
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/Ch12/query_tree.h:
--------------------------------------------------------------------------------
1 | /*
2 | query_tree.h
3 |
4 | DESCRIPTION
5 | This file contains the Query_tree class. It is responsible for containing the
6 | internal representation of the query to be executed. It provides methods for
7 | optimizing and forming and inspecting the query tree. This class is the very
8 | heart of the DBXP query capability! It also provides the ability to store
9 | a binary "compiled" form of the query.
10 |
11 | NOTES
12 | The data structure is a binary tree that can have 0, 1, or 2 children. Only
13 | Join operations can have 2 children. All other operations have 0 or 1
14 | children. Each node in the tree is an operation and the links to children
15 | are the pipeline.
16 |
17 | SEE ALSO
18 | query_tree.cc
19 | */
20 | #include "sql_priv.h"
21 | #include "sql_class.h"
22 | #include "table.h"
23 | #include "records.h"
24 |
25 | class Query_tree
26 | {
27 | public:
28 | enum query_node_type //this enumeration lists the available
29 | { //query node (operations)
30 | qntUndefined = 0,
31 | qntRestrict = 1,
32 | qntProject = 2,
33 | qntJoin = 3,
34 | qntSort = 4,
35 | qntDistinct = 5
36 | };
37 |
38 | enum join_con_type //this enumeration lists the available
39 | { //join operations supported
40 | jcUN = 0,
41 | jcNA = 1,
42 | jcON = 2,
43 | jcUS = 3
44 | };
45 |
46 | enum type_join //this enumeration lists the available
47 | { //join types supported.
48 | jnUNKNOWN = 0, //undefined
49 | jnINNER = 1,
50 | jnLEFTOUTER = 2,
51 | jnRIGHTOUTER = 3,
52 | jnFULLOUTER = 4,
53 | jnCROSSPRODUCT = 5,
54 | jnUNION = 6,
55 | jnINTERSECT = 7
56 | };
57 |
58 | enum AggregateType //used to add aggregate functions
59 | {
60 | atNONE = 0,
61 | atCOUNT = 1
62 | };
63 |
64 | /*
65 | STRUCTURE query_node
66 |
67 | DESCRIPTION
68 | This this structure contains all of the data for a query node:
69 |
70 | NodeId -- the internal id number for a node
71 | ParentNodeId -- the internal id for the parent node (used for insert)
72 | SubQuery -- is this the start of a subquery?
73 | Child -- is this a Left or Right child of the parent?
74 | NodeType -- synonymous with operation type
75 | JoinType -- if a join, this is the join operation
76 | join_con_type -- if this is a join, this is the "on" condition
77 | Expressions -- the expressions from the "where" clause for this node
78 | Join Expressions -- the join expressions from the "join" clause(s)
79 | Relations[] -- the relations for this operation (at most 2)
80 | PreemptPipeline -- does the pipeline need to be halted for a sort?
81 | Fields -- the attributes for the result set of this operation
82 | Left -- a pointer to the left child node
83 | Right -- a pointer to the right child node
84 | */
85 | struct query_node
86 | {
87 | query_node();
88 | //query_node(const query_node &o);
89 | ~query_node();
90 | int nodeid;
91 | int parent_nodeid;
92 | bool sub_query;
93 | bool child;
94 | query_node_type node_type;
95 | type_join join_type;
96 | join_con_type join_cond;
97 | Item *where_expr;
98 | Item *join_expr;
99 | TABLE_LIST *relations[4];
100 | bool preempt_pipeline;
101 | List
- *fields;
102 | query_node *left;
103 | query_node *right;
104 | };
105 |
106 | query_node *root; //The ROOT node of the tree
107 |
108 | ~Query_tree(void);
109 | void ShowPlan(query_node *QN, bool PrintOnRight);
110 |
111 | };
112 |
--------------------------------------------------------------------------------
/Ch12/source_Ch12.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch12/source_Ch12.zip
--------------------------------------------------------------------------------
/Ch12/sql_dbxp_parse.cc:
--------------------------------------------------------------------------------
1 | /*
2 | sql_dbxp_parse.cc
3 |
4 | DESCRIPTION
5 | This file contains methods to execute the DBXP SELECT query statements.
6 |
7 | SEE ALSO
8 | query_tree.cc
9 | */
10 | #include "query_tree.h"
11 |
12 | /*
13 | Build Query Tree
14 |
15 | SYNOPSIS
16 | build_query_tree()
17 | THD *thd IN the current thread
18 | LEX *lex IN the pointer to the current parsed structure
19 | TABLE_LIST *tables IN the list of tables identified in the query
20 |
21 | DESCRIPTION
22 | This method returns a converted MySQL internal representation (IR) of a
23 | query as a query_tree.
24 |
25 | RETURN VALUE
26 | Success = Query_tree * -- the root of the new query tree.
27 | Failed = NULL
28 | */
29 | Query_tree *build_query_tree(THD *thd, LEX *lex, TABLE_LIST *tables)
30 | {
31 | DBUG_ENTER("build_query_tree");
32 | Query_tree *qt = new Query_tree();
33 | Query_tree::query_node *qn = new Query_tree::query_node();
34 | TABLE_LIST *table;
35 | int i = 0;
36 | int num_tables = 0;
37 |
38 | /* Create a new restrict node. */
39 | qn->parent_nodeid = -1;
40 | qn->child = false;
41 | qn->join_type = (Query_tree::type_join) 0;
42 | qn->nodeid = 0;
43 | qn->node_type = (Query_tree::query_node_type) 2;
44 | qn->left = 0;
45 | qn->right = 0;
46 |
47 | if(lex->select_lex.options & SELECT_DISTINCT)
48 | {
49 | //qt->set_distinct(true);
50 | }
51 |
52 | /* Get the tables (relations) */
53 | i = 0;
54 | for(table = tables; table; table = table->next_local)
55 | {
56 | num_tables++;
57 | qn->relations[i] = table;
58 | i++;
59 | }
60 |
61 | /* Populate attributes */
62 | qn->fields = &lex->select_lex.item_list;
63 | /* Process joins */
64 | if (num_tables > 0) //indicates more than 1 table processed
65 | for(table = tables; table; table = table->next_local)
66 | if (((Item *)table->join_cond() != 0) && (qn->join_expr == 0))
67 | qn->join_expr = (Item *)table->join_cond();
68 | qn->where_expr = lex->select_lex.where;
69 | qt->root = qn;
70 | DBUG_RETURN(qt);
71 | }
72 |
73 | /*
74 | Perform Select Command
75 |
76 | SYNOPSIS
77 | DBXP_select_command()
78 | THD *thd IN the current thread
79 |
80 | DESCRIPTION
81 | This method executes the SELECT command using the query tree and optimizer.
82 |
83 | RETURN VALUE
84 | Success = 0
85 | Failed = 1
86 | */
87 | int DBXP_select_command(THD *thd)
88 | {
89 | DBUG_ENTER("DBXP_select_command");
90 | Query_tree *qt = build_query_tree(thd, thd->lex,
91 | (TABLE_LIST*) thd->lex->select_lex.table_list.first);
92 | List
- field_list;
93 | Protocol *protocol= thd->protocol;
94 | field_list.push_back(new Item_empty_string("Database Experiment Project (DBXP)",40));
95 | if (protocol->send_result_set_metadata(&field_list,
96 | Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
97 | DBUG_RETURN(TRUE);
98 | protocol->prepare_for_resend();
99 | protocol->store("Query tree was built.", system_charset_info);
100 | if (protocol->write())
101 | DBUG_RETURN(TRUE);
102 | my_eof(thd);
103 | DBUG_RETURN(0);
104 | }
105 |
106 | /*
107 | Write to vio with printf.
108 |
109 | SYNOPSIS
110 | write_printf()
111 | Protocol *p IN the Protocol class
112 | char *first IN the first string to write
113 | char *last IN the last string to write
114 |
115 | DESCRIPTION
116 | This method writes to the vio routines printing the strings passed.
117 |
118 | RETURN VALUE
119 | Success = 0
120 | Failed = 1
121 | */
122 | int write_printf(Protocol *p, char *first, const char *last)
123 | {
124 | char *str = new char[1024];
125 |
126 | DBUG_ENTER("write_printf");
127 | strcpy(str, first);
128 | strcat(str, last);
129 | p->prepare_for_resend();
130 | p->store(str, system_charset_info);
131 | p->write();
132 | delete str;
133 | DBUG_RETURN(0);
134 | }
135 |
136 | /*
137 | Show Query Plan
138 |
139 | SYNOPSIS
140 | show_plan()
141 | Protocol *p IN the MySQL protocol class
142 | query_node *Root IN the root node of the query tree
143 | query_node *qn IN the starting node to be operated on.
144 | bool print_on_right IN indicates the printing should tab to the right
145 | of the display.
146 |
147 | DESCRIPTION
148 | This method prints the execute plan to the client via the protocol class
149 |
150 | WARNING
151 | This is a RECURSIVE method!
152 | Uses postorder traversal to draw the quey plan
153 |
154 | RETURN VALUE
155 | Success = 0
156 | Failed = 1
157 | */
158 | int show_plan(Protocol *p, Query_tree::query_node *root,
159 | Query_tree::query_node *qn, bool print_on_right)
160 | {
161 | DBUG_ENTER("show_plan");
162 |
163 | /* spacer is used to fill white space in the output */
164 | char *spacer = (char *)my_malloc(80, MYF(MY_ZEROFILL | MY_WME));
165 | char *tblname = (char *)my_malloc(256, MYF(MY_ZEROFILL | MY_WME));
166 | int i = 0;
167 |
168 | if(qn != 0)
169 | {
170 | show_plan(p, root, qn->left, print_on_right);
171 | show_plan(p, root, qn->right, true);
172 |
173 | /* draw incoming arrows */
174 | if(print_on_right)
175 | strcpy(spacer, " | ");
176 | else
177 | strcpy(spacer, " ");
178 |
179 | /* Write out the name of the database and table */
180 | if((qn->left == NULL) && (qn->right == NULL))
181 | {
182 | /*
183 | If this is a join, it has 2 children so we need to write
184 | the children nodes feeding the join node. Spaces are used
185 | to place the tables side-by-side.
186 | */
187 | if(qn->node_type == Query_tree::qntJoin)
188 | {
189 | strcpy(tblname, spacer);
190 | strcat(tblname, qn->relations[0]->db);
191 | strcat(tblname, ".");
192 | strcat(tblname, qn->relations[0]->table_name);
193 | if(strlen(tblname) < 15)
194 | strcat(tblname, " ");
195 | else
196 | strcat(tblname, " ");
197 | strcat(tblname, qn->relations[1]->db);
198 | strcat(tblname, ".");
199 | strcat(tblname, qn->relations[1]->table_name);
200 | write_printf(p, tblname, "");
201 | write_printf(p, spacer, " | |");
202 | write_printf(p, spacer, " | ----------------------------");
203 | write_printf(p, spacer, " | |");
204 | write_printf(p, spacer, " V V");
205 | }
206 | else
207 | {
208 | strcpy(tblname, spacer);
209 | strcat(tblname, qn->relations[0]->db);
210 | strcat(tblname, ".");
211 | strcat(tblname, qn->relations[0]->table_name);
212 | write_printf(p, tblname, "");
213 | write_printf(p, spacer, " |");
214 | write_printf(p, spacer, " |");
215 | write_printf(p, spacer, " |");
216 | write_printf(p, spacer, " V");
217 | }
218 | }
219 | else if((qn->left != 0) && (qn->right != 0))
220 | {
221 | write_printf(p, spacer, " | |");
222 | write_printf(p, spacer, " | ----------------------------");
223 | write_printf(p, spacer, " | |");
224 | write_printf(p, spacer, " V V");
225 | }
226 | else if((qn->left != 0) && (qn->right == 0))
227 | {
228 | write_printf(p, spacer, " |");
229 | write_printf(p, spacer, " |");
230 | write_printf(p, spacer, " |");
231 | write_printf(p, spacer, " V");
232 | }
233 | else if(qn->right != 0)
234 | {
235 | }
236 | write_printf(p, spacer, "-------------------");
237 |
238 | /* Write out the node type */
239 | switch(qn->node_type)
240 | {
241 | case Query_tree::qntProject:
242 | {
243 | write_printf(p, spacer, "| PROJECT |");
244 | write_printf(p, spacer, "-------------------");
245 | break;
246 | }
247 | case Query_tree::qntRestrict:
248 | {
249 | write_printf(p, spacer, "| RESTRICT |");
250 | write_printf(p, spacer, "-------------------");
251 | break;
252 | }
253 | case Query_tree::qntJoin:
254 | {
255 | write_printf(p, spacer, "| JOIN |");
256 | write_printf(p, spacer, "-------------------");
257 | break;
258 | }
259 | case Query_tree::qntDistinct:
260 | {
261 | write_printf(p, spacer, "| DISTINCT |");
262 | write_printf(p, spacer, "-------------------");
263 | break;
264 | }
265 | default:
266 | {
267 | write_printf(p, spacer, "| UNDEF |");
268 | write_printf(p, spacer, "-------------------");
269 | break;
270 | }
271 | }
272 | write_printf(p, spacer, "| Access Method: |");
273 | write_printf(p, spacer, "| iterator |");
274 | write_printf(p, spacer, "-------------------");
275 | if(qn == root)
276 | {
277 | write_printf(p, spacer, " |");
278 | write_printf(p, spacer, " |");
279 | write_printf(p, spacer, " V");
280 | write_printf(p, spacer, " Result Set");
281 | }
282 | }
283 | my_free(spacer);
284 | my_free(tblname);
285 | DBUG_RETURN(0);
286 | }
287 |
288 | /*
289 | Perform EXPLAIN command.
290 |
291 | SYNOPSIS
292 | DBXP_explain_select_command()
293 | THD *thd IN the current thread
294 |
295 | DESCRIPTION
296 | This method executes the EXPLAIN SELECT command.
297 |
298 | RETURN VALUE
299 | Success = 0
300 | Failed = 1
301 | */
302 | int DBXP_explain_select_command(THD *thd)
303 | {
304 | DBUG_ENTER("DBXP_explain_select_command");
305 | Query_tree *qt = build_query_tree(thd, thd->lex,
306 | (TABLE_LIST*) thd->lex->select_lex.table_list.first);
307 | List
- field_list;
308 | Protocol *protocol= thd->protocol;
309 | field_list.push_back(new Item_empty_string("Execution Path",NAME_LEN));
310 | if (protocol->send_result_set_metadata(&field_list,
311 | Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
312 | DBUG_RETURN(TRUE);
313 | protocol->prepare_for_resend();
314 | show_plan(protocol, qt->root, qt->root, false);
315 | my_eof(thd);
316 | DBUG_RETURN(0);
317 | }
318 |
--------------------------------------------------------------------------------
/Ch13/attribute.cc:
--------------------------------------------------------------------------------
1 | /*
2 | attribute.cc
3 |
4 | DESCRIPTION
5 | This file contains methods to encapsulate the attributes in a query.
6 |
7 | SEE ALSO
8 | attribute.h
9 | */
10 | #include "attribute.h"
11 |
12 | /*
13 | Constructor
14 |
15 | SYNOPSIS
16 | Attribute()
17 |
18 | DESCRIPTION
19 | Initializes the hidden attribute array.
20 | */
21 | Attribute::Attribute(void)
22 | {
23 | int i;
24 | for (i = 0; i < 256; i++)
25 | hidden[i] = false;
26 | }
27 |
28 | /*
29 | Remove Attribute
30 |
31 | SYNOPSIS
32 | remove_attribute()
33 | int num IN the number (starting at 0) of the sttribute to drop.
34 |
35 | DESCRIPTION
36 | This method removes the attribute from the collection.
37 |
38 | RETURN VALUE
39 | Success = true
40 | Failed = false
41 | */
42 | int Attribute::remove_attribute(int num)
43 | {
44 | int j = 0;
45 | List_iterator
- it(attr_list);
46 | Item *item = NULL;
47 |
48 | DBUG_ENTER("remove_attribute");
49 | if (num >= (int)attr_list.elements || num < 0)
50 | DBUG_RETURN(false);
51 | while ((item = it++))
52 | {
53 | if (j == num)
54 | {
55 | it.remove();
56 | DBUG_RETURN(true);
57 | }
58 | j++;
59 | }
60 | DBUG_RETURN(false);
61 | }
62 |
63 | /*
64 | Get Attribute
65 |
66 | SYNOPSIS
67 | get_attribute()
68 | int num IN the number of attribute to retrieve.
69 |
70 | DESCRIPTION
71 | This method returns the attribute at the index specified.
72 |
73 | RETURN VALUE
74 | Success = Item *
75 | Failed = NULL
76 | */
77 | Item *Attribute::get_attribute(int num)
78 | {
79 | int j = 0;
80 | List
- it(attr_list);
81 | Item *item = it.pop();
82 |
83 | DBUG_ENTER("get_attribute");
84 | if (num >= (int)attr_list.elements || num < 0)
85 | DBUG_RETURN(NULL);
86 | while ((j != num) && (item != NULL))
87 | {
88 | item = it.pop();
89 | j++;
90 | }
91 | if (j != num)
92 | item = 0;
93 | DBUG_RETURN(item);
94 | }
95 |
96 | /*
97 | Add Attribute
98 |
99 | SYNOPSIS
100 | add_attribute()
101 | bool append IN do you want to append (true) or prepend (false)?
102 | Item *new_item IN the item to be added.
103 |
104 | DESCRIPTION
105 | This method adds the attribute at the front or back of the list.
106 |
107 | RETURN VALUE
108 | Success = 0
109 | Failed = 1
110 | */
111 | int Attribute::add_attribute(bool append, Item *new_item)
112 | {
113 | DBUG_ENTER("add_attribute");
114 | if (append)
115 | attr_list.push_back(new_item);
116 | else
117 | attr_list.push_front(new_item);
118 | DBUG_RETURN(0);
119 | }
120 |
121 | /*
122 | Number of Attributes
123 |
124 | SYNOPSIS
125 | num_attributes()
126 |
127 | DESCRIPTION
128 | This method returns the number of attributes in the list.
129 |
130 | RETURN VALUE
131 | int Number of attributes in list
132 | */
133 | int Attribute::num_attributes()
134 | {
135 | DBUG_ENTER("num_attributes");
136 | DBUG_RETURN(attr_list.elements);
137 | }
138 |
139 | /*
140 | Find index of Attribute
141 |
142 | SYNOPSIS
143 | index_of()
144 | char *table IN table name of the attribute
145 | char *value IN the name of the attribute
146 |
147 | DESCRIPTION
148 | This method returns the index (number) of attribute specified.
149 |
150 | RETURN VALUE
151 | Success = int Number of attribute
152 | Failed = -1
153 | */
154 | int Attribute::index_of(char *table, char *value)
155 | {
156 | List_iterator
- it(attr_list);
157 | Item *item;
158 | int i = 0;
159 | int j = -1;
160 | bool found = false;
161 |
162 | DBUG_ENTER("index_of");
163 | while ((item = it++) && !found)
164 | {
165 | if ((strcasecmp(((Field *)item)->field_name, value) == 0) &&
166 | ((table == NULL) ||
167 | (strcasecmp(*((Field *)item)->table_name, table) == 0)))
168 | {
169 | j = i;
170 | found = true;
171 | }
172 | i++;
173 | }
174 | DBUG_RETURN(j);
175 | }
176 |
177 | /*
178 | Hide Attribute
179 |
180 | SYNOPSIS
181 | hide_attribute()
182 | int num IN the number of attribute to hide.
183 |
184 | DESCRIPTION
185 | This method sets the hidden property of the attribute to specify
186 | that the attribute is not to be sent to the client (used internally)
187 | by the optimizer.
188 |
189 | RETURN VALUE
190 | Success = 0
191 | Failed = -1
192 | */
193 | int Attribute::hide_attribute(Item *item, bool hide)
194 | {
195 | int i;
196 | DBUG_ENTER("hide_attribute");
197 | i = index_of((char *)*((Field *)item)->table_name,
198 | (char *)((Field *)item)->field_name);
199 | if (i > -1)
200 | hidden[i] = hide;
201 | DBUG_RETURN(0);
202 | }
203 |
204 | /*
205 | Get string value of attributes
206 |
207 | SYNOPSIS
208 | to_string()
209 |
210 | DESCRIPTION
211 | This method returns a formatted string of the attributes in the list.
212 |
213 | RETURN VALUE
214 | Success = char *
215 | Failed = ""
216 | */
217 | char *Attribute::to_string()
218 | {
219 | List_iterator
- it(attr_list);
220 | char *str = (char *)my_malloc(1024, MYF(MY_ZEROFILL | MY_WME));
221 | Item *item;
222 | int j = 0;
223 |
224 | DBUG_ENTER("to_string");
225 | strcpy(str, "");
226 | while ((item = it++))
227 | {
228 | if (j)
229 | strcat(str, ", ");
230 | if (*((Field *)item)->table_name)
231 | {
232 | strcat(str, *((Field *)item)->table_name);
233 | strcat(str, ".");
234 | }
235 | strcat(str, ((Field *)item)->field_name);
236 | if (!j)
237 | j = 1;
238 | }
239 | DBUG_RETURN(str);
240 | }
241 |
--------------------------------------------------------------------------------
/Ch13/attribute.h:
--------------------------------------------------------------------------------
1 | #include "sql_priv.h"
2 | #include "sql_class.h"
3 | #include "table.h"
4 |
5 | class Attribute
6 | {
7 | public:
8 | Attribute(void);
9 | int remove_attribute(int num);
10 | Item *get_attribute(int num);
11 | int add_attribute(bool append, Item *new_item);
12 | int num_attributes();
13 | int index_of(char *table, char *value);
14 | int hide_attribute(Item *item, bool hide);
15 | char *to_string();
16 | private:
17 | List
- attr_list;
18 | bool hidden[256];
19 | };
20 |
--------------------------------------------------------------------------------
/Ch13/ch13.result:
--------------------------------------------------------------------------------
1 | DROP DATABASE IF EXISTS expert_mysql;
2 | Warnings:
3 | Note 1008 Can't drop database 'expert_mysql'; database doesn't exist
4 | CREATE DATABASE expert_mysql;
5 | USE expert_mysql;
6 | CREATE TABLE `building` (
7 | `dir_code` char(4) NOT NULL,
8 | `building` char(6) NOT NULL
9 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
10 | CREATE TABLE `directorate` (
11 | `dir_code` char(4) NOT NULL,
12 | `dir_name` char(30) DEFAULT NULL,
13 | `dir_head_id` char(9) DEFAULT NULL,
14 | PRIMARY KEY (`dir_code`)
15 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
16 | CREATE TABLE `staff` (
17 | `id` char(9) NOT NULL,
18 | `first_name` char(20) DEFAULT NULL,
19 | `mid_name` char(20) DEFAULT NULL,
20 | `last_name` char(30) DEFAULT NULL,
21 | `sex` char(1) DEFAULT NULL,
22 | `salary` int(11) DEFAULT NULL,
23 | `mgr_id` char(9) DEFAULT NULL,
24 | PRIMARY KEY (`id`)
25 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
26 | CREATE TABLE `tasking` (
27 | `id` char(9) NOT NULL,
28 | `project_number` char(9) NOT NULL,
29 | `hours_worked` double DEFAULT NULL
30 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
31 | USE expert_mysql;
32 | INSERT INTO expert_mysql.building VALUES ('N41', '1300');
33 | INSERT INTO expert_mysql.building VALUES ('N01', '1453');
34 | INSERT INTO expert_mysql.building VALUES ('M00', '1000');
35 | INSERT INTO expert_mysql.building VALUES ('N41', '1301');
36 | INSERT INTO expert_mysql.building VALUES ('N41', '1305');
37 | INSERT INTO expert_mysql.directorate VALUES ('N41', 'Development', '333445555');
38 | INSERT INTO expert_mysql.directorate VALUES ('N01', 'Human Resources', '123654321');
39 | INSERT INTO expert_mysql.directorate VALUES ('M00', 'Management', '333444444');
40 | INSERT INTO expert_mysql.staff VALUES ('333445555', 'John', 'Q', 'Smith', 'M', 30000, '333444444');
41 | INSERT INTO expert_mysql.staff VALUES ('123763153', 'William', 'E', 'Walters', 'M', 25000, '123654321');
42 | INSERT INTO expert_mysql.staff VALUES ('333444444', 'Alicia', 'F', 'St.Cruz', 'F', 25000, 'None');
43 | INSERT INTO expert_mysql.staff VALUES ('921312388', 'Goy', 'X', 'Hong', 'F', 40000, '123654321');
44 | INSERT INTO expert_mysql.staff VALUES ('800122337', 'Rajesh', 'G', 'Kardakarna', 'M', 38000, '333445555');
45 | INSERT INTO expert_mysql.staff VALUES ('820123637', 'Monty', 'C', 'Smythe', 'M', 38000, '333445555');
46 | INSERT INTO expert_mysql.staff VALUES ('830132335', 'Richard', 'E', 'Jones', 'M', 38000, '333445555');
47 | INSERT INTO expert_mysql.staff VALUES ('333445665', 'Edward', 'E', 'Engles', 'M', 25000, '333445555');
48 | INSERT INTO expert_mysql.staff VALUES ('123654321', 'Beware', 'D', 'Borg', 'F', 55000, '333444444');
49 | INSERT INTO expert_mysql.staff VALUES ('123456789', 'Wilma', 'N', 'Maxima', 'F', 43000, '333445555');
50 | INSERT INTO expert_mysql.tasking VALUES ('333445555', '405', 23);
51 | INSERT INTO expert_mysql.tasking VALUES ('123763153', '405', 33.5);
52 | INSERT INTO expert_mysql.tasking VALUES ('921312388', '601', 44);
53 | INSERT INTO expert_mysql.tasking VALUES ('800122337', '300', 13);
54 | INSERT INTO expert_mysql.tasking VALUES ('820123637', '300', 9.5);
55 | INSERT INTO expert_mysql.tasking VALUES ('830132335', '401', 8.5);
56 | INSERT INTO expert_mysql.tasking VALUES ('333445555', '300', 11);
57 | INSERT INTO expert_mysql.tasking VALUES ('921312388', '500', 13);
58 | INSERT INTO expert_mysql.tasking VALUES ('800122337', '300', 44);
59 | INSERT INTO expert_mysql.tasking VALUES ('820123637', '401', 500.5);
60 | INSERT INTO expert_mysql.tasking VALUES ('830132335', '400', 12);
61 | INSERT INTO expert_mysql.tasking VALUES ('333445665', '600', 300.25);
62 | INSERT INTO expert_mysql.tasking VALUES ('123654321', '607', 444.75);
63 | INSERT INTO expert_mysql.tasking VALUES ('123456789', '300', 1000);
64 | DBXP_SELECT * FROM staff;
65 | Execution Path
66 | expert_mysql.staff
67 | |
68 | |
69 | |
70 | V
71 | -------------------
72 | | PROJECT |
73 | -------------------
74 | | Access Method: |
75 | | iterator |
76 | -------------------
77 | |
78 | |
79 | V
80 | Result Set
81 | DBXP_SELECT id FROM staff WHERE staff.id = '123456789';
82 | Execution Path
83 | expert_mysql.staff
84 | |
85 | |
86 | |
87 | V
88 | -------------------
89 | | RESTRICT |
90 | -------------------
91 | | Access Method: |
92 | | iterator |
93 | -------------------
94 | |
95 | |
96 | |
97 | V
98 | -------------------
99 | | PROJECT |
100 | -------------------
101 | | Access Method: |
102 | | iterator |
103 | -------------------
104 | |
105 | |
106 | V
107 | Result Set
108 | DBXP_SELECT id, dir_name FROM staff, directorate
109 | WHERE staff.mgr_id = directorate.dir_head_id;
110 | Execution Path
111 | expert_mysql.staff
112 | |
113 | |
114 | |
115 | V
116 | -------------------
117 | | PROJECT |
118 | -------------------
119 | | Access Method: |
120 | | iterator |
121 | -------------------
122 | | expert_mysql.directorate
123 | | |
124 | | |
125 | | |
126 | | V
127 | | -------------------
128 | | | PROJECT |
129 | | -------------------
130 | | | Access Method: |
131 | | | iterator |
132 | | -------------------
133 | | |
134 | | ----------------------------
135 | | |
136 | V V
137 | -------------------
138 | | JOIN |
139 | -------------------
140 | | Access Method: |
141 | | iterator |
142 | -------------------
143 | |
144 | |
145 | V
146 | Result Set
147 | DBXP_SELECT * FROM staff JOIN tasking ON staff.id = tasking.id
148 | WHERE staff.id = '123456789';
149 | Execution Path
150 | expert_mysql.staff
151 | |
152 | |
153 | |
154 | V
155 | -------------------
156 | | RESTRICT |
157 | -------------------
158 | | Access Method: |
159 | | iterator |
160 | -------------------
161 | | expert_mysql.tasking
162 | | |
163 | | |
164 | | |
165 | | V
166 | | -------------------
167 | | | PROJECT |
168 | | -------------------
169 | | | Access Method: |
170 | | | iterator |
171 | | -------------------
172 | | |
173 | | ----------------------------
174 | | |
175 | V V
176 | -------------------
177 | | JOIN |
178 | -------------------
179 | | Access Method: |
180 | | iterator |
181 | -------------------
182 | |
183 | |
184 | V
185 | Result Set
186 | DROP DATABASE expert_mysql;
187 |
--------------------------------------------------------------------------------
/Ch13/ch13.test:
--------------------------------------------------------------------------------
1 | #
2 | # Sample test to test the DBXP_SELECT optimizer
3 | #
4 |
5 | --source include/ch13.sql
6 |
7 | # Test 1:
8 | DBXP_SELECT * FROM staff;
9 |
10 | # Test 2:
11 | DBXP_SELECT id FROM staff WHERE staff.id = '123456789';
12 |
13 | # Test 3:
14 | DBXP_SELECT id, dir_name FROM staff, directorate
15 | WHERE staff.mgr_id = directorate.dir_head_id;
16 |
17 | # Test 4:
18 | DBXP_SELECT * FROM staff JOIN tasking ON staff.id = tasking.id
19 | WHERE staff.id = '123456789';
20 |
21 | DROP DATABASE expert_mysql;
22 |
--------------------------------------------------------------------------------
/Ch13/ch13.txt:
--------------------------------------------------------------------------------
1 | DBXP_SELECT * FROM staff' at line 1
2 | +--------------------------+
3 | | Execution Path |
4 | +--------------------------+
5 | | expert_mysql.staff |
6 | | | |
7 | | | |
8 | | | |
9 | | V |
10 | | ------------------- |
11 | | | RESTRICT | |
12 | | ------------------- |
13 | | | Access Method: | |
14 | | | iterator | |
15 | | ------------------- |
16 | | | |
17 | | | |
18 | | | |
19 | | V |
20 | | ------------------- |
21 | | | PROJECT | |
22 | | ------------------- |
23 | | | Access Method: | |
24 | | | iterator | |
25 | | ------------------- |
26 | | | |
27 | | | |
28 | | V |
29 | | Result Set |
30 | +--------------------------+
31 | 25 rows in set (0.00 sec)
32 |
33 | +----------------------------------------------------+
34 | | Execution Path |
35 | +----------------------------------------------------+
36 | | expert_mysql.staff |
37 | | | |
38 | | | |
39 | | | |
40 | | V |
41 | | ------------------- |
42 | | | PROJECT | |
43 | | ------------------- |
44 | | | Access Method: | |
45 | | | iterator | |
46 | | ------------------- |
47 | | | expert_mysql.directorate |
48 | | | | |
49 | | | | |
50 | | | | |
51 | | | V |
52 | | | ------------------- |
53 | | | | PROJECT | |
54 | | | ------------------- |
55 | | | | Access Method: | |
56 | | | | iterator | |
57 | | | ------------------- |
58 | | | | |
59 | | | ---------------------------- |
60 | | | | |
61 | | V V |
62 | | ------------------- |
63 | | | JOIN | |
64 | | ------------------- |
65 | | | Access Method: | |
66 | | | iterator | |
67 | | ------------------- |
68 | | | |
69 | | | |
70 | | V |
71 | | Result Set |
72 | +----------------------------------------------------+
73 | 36 rows in set (0.00 sec)
74 |
75 | +------------------------------------------------+
76 | | Execution Path |
77 | +------------------------------------------------+
78 | | expert_mysql.staff |
79 | | | |
80 | | | |
81 | | | |
82 | | V |
83 | | ------------------- |
84 | | | RESTRICT | |
85 | | ------------------- |
86 | | | Access Method: | |
87 | | | iterator | |
88 | | ------------------- |
89 | | | expert_mysql.tasking |
90 | | | | |
91 | | | | |
92 | | | | |
93 | | | V |
94 | | | ------------------- |
95 | | | | PROJECT | |
96 | | | ------------------- |
97 | | | | Access Method: | |
98 | | | | iterator | |
99 | | | ------------------- |
100 | | | | |
101 | | | ---------------------------- |
102 | | | | |
103 | | V V |
104 | | ------------------- |
105 | | | JOIN | |
106 | | ------------------- |
107 | | | Access Method: | |
108 | | | iterator | |
109 | | ------------------- |
110 | | | |
111 | | | |
112 | | V |
113 | | Result Set |
114 | +------------------------------------------------+
115 | 36 rows in set (0.00 sec)
116 |
117 | Query OK, 4 rows affected (0.00 sec)
118 |
--------------------------------------------------------------------------------
/Ch13/ch13_results.txt:
--------------------------------------------------------------------------------
1 | mysql> explain dbxp_select * from staff;
2 | +--------------------------+
3 | | Execution Path |
4 | +--------------------------+
5 | | expert_mysql.staff |
6 | | | |
7 | | | |
8 | | | |
9 | | V |
10 | | ------------------- |
11 | | | PROJECT | |
12 | | ------------------- |
13 | | | Access Method: | |
14 | | | iterator | |
15 | | ------------------- |
16 | | | |
17 | | | |
18 | | V |
19 | | Result Set |
20 | +--------------------------+
21 | 15 rows in set (0.00 sec)
22 |
23 | mysql> explain dbxp_select id FROM staff WHERE staff.id = '123456789';
24 | +--------------------------+
25 | | Execution Path |
26 | +--------------------------+
27 | | expert_mysql.staff |
28 | | | |
29 | | | |
30 | | | |
31 | | V |
32 | | ------------------- |
33 | | | RESTRICT | |
34 | | ------------------- |
35 | | | Access Method: | |
36 | | | iterator | |
37 | | ------------------- |
38 | | | |
39 | | | |
40 | | | |
41 | | V |
42 | | ------------------- |
43 | | | PROJECT | |
44 | | ------------------- |
45 | | | Access Method: | |
46 | | | iterator | |
47 | | ------------------- |
48 | | | |
49 | | | |
50 | | V |
51 | | Result Set |
52 | +--------------------------+
53 | 25 rows in set (0.00 sec)
54 |
55 | mysql> explain dbxp_select id, dir_name FROM staff, directorate WHERE staff.dno = directorate.dnumber;
56 | ERROR 1054 (42S22): Unknown column 'directorate.dnumber' in 'field list'
57 | mysql> explain dbxp_select id, dir_name FROM staff, directorate WHERE staff.dno = directorate.d;
58 | ERROR 1054 (42S22): Unknown column 'directorate.d' in 'field list'
59 | mysql> explain directorate
60 | -> ;
61 | +-------------+----------+------+-----+---------+-------+
62 | | Field | Type | Null | Key | Default | Extra |
63 | +-------------+----------+------+-----+---------+-------+
64 | | dir_code | char(4) | NO | PRI | NULL | |
65 | | dir_name | char(30) | YES | | NULL | |
66 | | dir_head_id | char(9) | YES | | NULL | |
67 | +-------------+----------+------+-----+---------+-------+
68 | 3 rows in set (0.00 sec)
69 |
70 | mysql> explain dbxp_select id, dir_name FROM staff, directorate WHERE staff.dno = directorate.dir_code;
71 | ERROR 1054 (42S22): Unknown column 'staff.dno' in 'field list'
72 | mysql> explain dbxp_select id, dir_name FROM staff, directorate WHERE staff.dno = directorate.dir_code;
73 | ERROR 1054 (42S22): Unknown column 'staff.dno' in 'field list'
74 | mysql> explain staff;
75 | +------------+----------+------+-----+---------+-------+
76 | | Field | Type | Null | Key | Default | Extra |
77 | +------------+----------+------+-----+---------+-------+
78 | | id | char(9) | NO | PRI | NULL | |
79 | | first_name | char(20) | YES | | NULL | |
80 | | mid_name | char(20) | YES | | NULL | |
81 | | last_name | char(30) | YES | | NULL | |
82 | | sex | char(1) | YES | | NULL | |
83 | | salary | int(11) | YES | | NULL | |
84 | | mgr_id | char(9) | YES | | NULL | |
85 | +------------+----------+------+-----+---------+-------+
86 | 7 rows in set (0.00 sec)
87 |
88 | mysql> explain dbxp_select id, dir_name FROM staff, directorate WHERE staff.mgr_id = directorate.dir_code;
89 | +----------------------------------------------------+
90 | | Execution Path |
91 | +----------------------------------------------------+
92 | | expert_mysql.staff |
93 | | | |
94 | | | |
95 | | | |
96 | | V |
97 | | ------------------- |
98 | | | PROJECT | |
99 | | ------------------- |
100 | | | Access Method: | |
101 | | | iterator | |
102 | | ------------------- |
103 | | | expert_mysql.directorate |
104 | | | | |
105 | | | | |
106 | | | | |
107 | | | V |
108 | | | ------------------- |
109 | | | | PROJECT | |
110 | | | ------------------- |
111 | | | | Access Method: | |
112 | | | | iterator | |
113 | | | ------------------- |
114 | | | | |
115 | | | ---------------------------- |
116 | | | | |
117 | | V V |
118 | | ------------------- |
119 | | | JOIN | |
120 | | ------------------- |
121 | | | Access Method: | |
122 | | | iterator | |
123 | | ------------------- |
124 | | | |
125 | | | |
126 | | V |
127 | | Result Set |
128 | +----------------------------------------------------+
129 | 36 rows in set (0.00 sec)
130 |
131 | mysql> explain dbxp_select FROM staff JOIN tasking ON staff.id = tasking.id WHERE staff.id = '123456789';
132 | +------------------------------------------------+
133 | | Execution Path |
134 | +------------------------------------------------+
135 | | expert_mysql.staff |
136 | | | |
137 | | | |
138 | | | |
139 | | V |
140 | | ------------------- |
141 | | | RESTRICT | |
142 | | ------------------- |
143 | | | Access Method: | |
144 | | | iterator | |
145 | | ------------------- |
146 | | | expert_mysql.tasking |
147 | | | | |
148 | | | | |
149 | | | | |
150 | | | V |
151 | | | ------------------- |
152 | | | | PROJECT | |
153 | | | ------------------- |
154 | | | | Access Method: | |
155 | | | | iterator | |
156 | | | ------------------- |
157 | | | | |
158 | | | ---------------------------- |
159 | | | | |
160 | | V V |
161 | | ------------------- |
162 | | | JOIN | |
163 | | ------------------- |
164 | | | Access Method: | |
165 | | | iterator | |
166 | | ------------------- |
167 | | | |
168 | | | |
169 | | V |
170 | | Result Set |
171 | +------------------------------------------------+
172 | 36 rows in set (0.00 sec)
173 |
--------------------------------------------------------------------------------
/Ch13/expression.h:
--------------------------------------------------------------------------------
1 | #include "sql_priv.h"
2 | #include "sql_class.h"
3 | #include "table.h"
4 | #include
5 |
6 | struct expr_node
7 | {
8 | Item *left_op;
9 | Item *operation;
10 | Item *right_op;
11 | Item *junction;
12 | expr_node *next;
13 | };
14 |
15 | class Expression
16 | {
17 | public:
18 | Expression(void);
19 | int remove_expression(int num, bool free);
20 | expr_node *get_expression(int num);
21 | int add_expression(bool append, expr_node *new_item);
22 | int num_expressions();
23 | int index_of(char *table, char *value);
24 | int reduce_expressions(TABLE *table);
25 | bool has_table(char *table);
26 | int convert(THD *thd, Item *mysql_expr);
27 | char *to_string();
28 | bool evaluate(TABLE *table1);
29 | int compare_join(expr_node *expr, TABLE *t1, TABLE *t2);
30 | int get_join_expr(Expression *where_expr);
31 | private:
32 | expr_node *root;
33 | Field *find_field(TABLE *tbl, char *name);
34 | bool compare(expr_node *expr, TABLE *t1);
35 | int num_expr;
36 | };
37 |
--------------------------------------------------------------------------------
/Ch13/query_tree.h:
--------------------------------------------------------------------------------
1 | /*
2 | Query_tree.h
3 |
4 | DESCRIPTION
5 | This file contains the Query_tree class. It is responsible for containing the
6 | internal representation of the query to be executed. It provides methods for
7 | optimizing and forming and inspecting the query tree. This class is the very
8 | heart of the DBXP query capability! It also provides the ability to store
9 | a binary "compiled" form of the query.
10 |
11 | NOTES
12 | The data structure is a binary tree that can have 0, 1, or 2 children. Only
13 | Join operations can have 2 children. All other operations have 0 or 1
14 | children. Each node in the tree is an operation and the links to children
15 | are the pipeline.
16 |
17 | SEE ALSO
18 | query_tree.cc
19 | */
20 | #include "attribute.h"
21 | #include "expression.h"
22 | #include "sql_priv.h"
23 | #include "sql_class.h"
24 | #include "table.h"
25 | #include "records.h"
26 |
27 | const int MAXNODETABLES = 4;
28 | const int LEFTCHILD = 0;
29 | const int RIGHTCHILD = 1;
30 |
31 | class Query_tree
32 | {
33 | public:
34 | enum query_node_type //this enumeration lists the available
35 | { //query node (operations)
36 | qntUndefined = 0,
37 | qntRestrict = 1,
38 | qntProject = 2,
39 | qntJoin = 3,
40 | qntSort = 4,
41 | qntDistinct = 5
42 | };
43 |
44 | enum join_con_type //this enumeration lists the available
45 | { //join operations supported
46 | jcUN = 0,
47 | jcNA = 1,
48 | jcON = 2,
49 | jcUS = 3
50 | };
51 |
52 | enum type_join //this enumeration lists the available
53 | { //join types supported.
54 | jnUNKNOWN = 0, //undefined
55 | jnINNER = 1,
56 | jnLEFTOUTER = 2,
57 | jnRIGHTOUTER = 3,
58 | jnFULLOUTER = 4,
59 | jnCROSSPRODUCT = 5,
60 | jnUNION = 6,
61 | jnINTERSECT = 7
62 | };
63 |
64 | enum AggregateType //used to add aggregate functions
65 | {
66 | atNONE = 0,
67 | atCOUNT = 1
68 | };
69 |
70 | /*
71 | STRUCTURE query_node
72 |
73 | DESCRIPTION
74 | This this structure contains all of the data for a query node:
75 |
76 | NodeId -- the internal id number for a node
77 | ParentNodeId -- the internal id for the parent node (used for insert)
78 | SubQuery -- is this the start of a subquery?
79 | Child -- is this a Left or Right child of the parent?
80 | NodeType -- synonymous with operation type
81 | JoinType -- if a join, this is the join operation
82 | join_con_type -- if this is a join, this is the "on" condition
83 | Expressions -- the expressions from the "where" clause for this node
84 | Join Expressions -- the join expressions from the "join" clause(s)
85 | Relations[] -- the relations for this operation (at most 2)
86 | PreemptPipeline -- does the pipeline need to be halted for a sort?
87 | Fields -- the attributes for the result set of this operation
88 | Left -- a pointer to the left child node
89 | Right -- a pointer to the right child node
90 | */
91 | struct query_node
92 | {
93 | query_node();
94 | ~query_node();
95 | int nodeid;
96 | int parent_nodeid;
97 | bool sub_query;
98 | int child;
99 | query_node_type node_type;
100 | type_join join_type;
101 | join_con_type join_cond;
102 | Expression *where_expr;
103 | Expression *join_expr;
104 | TABLE_LIST *relations[MAXNODETABLES];
105 | int eof[MAXNODETABLES];
106 | int ndx[MAXNODETABLES];
107 | bool preempt_pipeline;
108 | Attribute *attributes;
109 | query_node *left;
110 | query_node *right;
111 | };
112 |
113 | struct record_buff
114 | {
115 | uchar *field_ptr;
116 | long field_length;
117 | record_buff *next;
118 | record_buff *prev;
119 | READ_RECORD *record;
120 | };
121 |
122 | query_node *root; //The ROOT node of the tree
123 |
124 | Query_tree(void);
125 | ~Query_tree(void);
126 | int init_node(query_node *qn);
127 | int heuristic_optimization();
128 | int cost_optimization();
129 | int insert_attribute(query_node *qn, Item *c);
130 | bool distinct;
131 | int prepare(query_node *qn);
132 | int cleanup(query_node *qn);
133 | bool Eof(query_node *qn);
134 | READ_RECORD *get_next(query_node *qn);
135 | List
- result_fields;
136 |
137 | private:
138 | bool h_opt; //has query been optimized (rules)?
139 | bool c_opt; //has query been optimized (cost)?
140 | READ_RECORD *lbuff;
141 | READ_RECORD *rbuff;
142 | record_buff *left_record_buff;
143 | record_buff *right_record_buff;
144 | record_buff *left_record_buffer_ptr;
145 | record_buff *right_record_buffer_ptr;
146 |
147 | int push_projections(query_node *qn, query_node *pNode);
148 | query_node *find_projection(query_node *qn);
149 | bool is_leaf(query_node *qn);
150 | bool has_relation(query_node *qn, char *Table);
151 | bool has_attribute(query_node *qn, Item *a);
152 | int del_attribute(query_node *qn, Item *a);
153 | int push_restrictions(query_node *qn, query_node *pNode);
154 | query_node *find_restriction(query_node *qn);
155 | query_node *find_join(query_node *qn);
156 | int push_joins(query_node *qn, query_node *pNode);
157 | int prune_tree(query_node *prev, query_node *cur_node);
158 | int balance_joins(query_node *qn);
159 | int split_restrict_with_project(query_node *qn);
160 | int split_restrict_with_join(query_node *qn);
161 | int split_project_with_join(query_node *qn);
162 | bool find_table_in_tree(query_node *qn, char *tbl);
163 | bool find_table_in_expr(Expression *expr, char *tbl);
164 | bool find_attr_in_expr(Expression *expr, char *tbl, char *value);
165 | int apply_indexes(query_node *qn);
166 | bool do_restrict(query_node *qn, READ_RECORD *t);
167 | READ_RECORD *do_project(query_node *qn, READ_RECORD *t);
168 | READ_RECORD *do_join(query_node *qn);
169 | int find_index_in_expr(Expression *e, char *tbl);
170 | TABLE *get_table(query_node *qn);
171 | int insertion_sort(bool left, Field *field, READ_RECORD *rcd);
172 | int check_rollback(record_buff *cur_left, record_buff *curr_left_prev,
173 | record_buff *cur_right, record_buff *cur_right_prev);
174 | };
175 |
176 |
--------------------------------------------------------------------------------
/Ch13/source_Ch13.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch13/source_Ch13.zip
--------------------------------------------------------------------------------
/Ch14/attribute.cc:
--------------------------------------------------------------------------------
1 | /*
2 | attribute.cc
3 |
4 | DESCRIPTION
5 | This file contains methods to encapsulate the attributes in a query.
6 |
7 | SEE ALSO
8 | attribute.h
9 | */
10 | #include "attribute.h"
11 |
12 | /*
13 | Constructor
14 |
15 | SYNOPSIS
16 | Attribute()
17 |
18 | DESCRIPTION
19 | Initializes the hidden attribute array.
20 | */
21 | Attribute::Attribute(void)
22 | {
23 | int i;
24 | for (i = 0; i < 256; i++)
25 | hidden[i] = false;
26 | }
27 |
28 | /*
29 | Remove Attribute
30 |
31 | SYNOPSIS
32 | remove_attribute()
33 | int num IN the number (starting at 0) of the sttribute to drop.
34 |
35 | DESCRIPTION
36 | This method removes the attribute from the collection.
37 |
38 | RETURN VALUE
39 | Success = true
40 | Failed = false
41 | */
42 | int Attribute::remove_attribute(int num)
43 | {
44 | int j = 0;
45 | List_iterator
- it(attr_list);
46 | Item *item = NULL;
47 |
48 | DBUG_ENTER("remove_attribute");
49 | if (num >= (int)attr_list.elements || num < 0)
50 | DBUG_RETURN(false);
51 | while ((item = it++))
52 | {
53 | if (j == num)
54 | {
55 | it.remove();
56 | DBUG_RETURN(true);
57 | }
58 | j++;
59 | }
60 | DBUG_RETURN(false);
61 | }
62 |
63 | /*
64 | Get Attribute
65 |
66 | SYNOPSIS
67 | get_attribute()
68 | int num IN the number of attribute to retrieve.
69 |
70 | DESCRIPTION
71 | This method returns the attribute at the index specified.
72 |
73 | RETURN VALUE
74 | Success = Item *
75 | Failed = NULL
76 | */
77 | Item *Attribute::get_attribute(int num)
78 | {
79 | int j = 0;
80 | List
- it(attr_list);
81 | Item *item = it.pop();
82 |
83 | DBUG_ENTER("get_attribute");
84 | if (num >= (int)attr_list.elements || num < 0)
85 | DBUG_RETURN(NULL);
86 | while ((j != num) && (item != NULL))
87 | {
88 | item = it.pop();
89 | j++;
90 | }
91 | if (j != num)
92 | item = 0;
93 | DBUG_RETURN(item);
94 | }
95 |
96 | /*
97 | Add Attribute
98 |
99 | SYNOPSIS
100 | add_attribute()
101 | bool append IN do you want to append (true) or prepend (false)?
102 | Item *new_item IN the item to be added.
103 |
104 | DESCRIPTION
105 | This method adds the attribute at the front or back of the list.
106 |
107 | RETURN VALUE
108 | Success = 0
109 | Failed = 1
110 | */
111 | int Attribute::add_attribute(bool append, Item *new_item)
112 | {
113 | DBUG_ENTER("add_attribute");
114 | if (append)
115 | attr_list.push_back(new_item);
116 | else
117 | attr_list.push_front(new_item);
118 | DBUG_RETURN(0);
119 | }
120 |
121 | /*
122 | Number of Attributes
123 |
124 | SYNOPSIS
125 | num_attributes()
126 |
127 | DESCRIPTION
128 | This method returns the number of attributes in the list.
129 |
130 | RETURN VALUE
131 | int Number of attributes in list
132 | */
133 | int Attribute::num_attributes()
134 | {
135 | DBUG_ENTER("num_attributes");
136 | DBUG_RETURN(attr_list.elements);
137 | }
138 |
139 | /*
140 | Find index of Attribute
141 |
142 | SYNOPSIS
143 | index_of()
144 | char *table IN table name of the attribute
145 | char *value IN the name of the attribute
146 |
147 | DESCRIPTION
148 | This method returns the index (number) of attribute specified.
149 |
150 | RETURN VALUE
151 | Success = int Number of attribute
152 | Failed = -1
153 | */
154 | int Attribute::index_of(char *table, char *value)
155 | {
156 | List_iterator
- it(attr_list);
157 | Item *item;
158 | int i = 0;
159 | int j = -1;
160 | bool found = false;
161 |
162 | DBUG_ENTER("index_of");
163 | while ((item = it++) && !found)
164 | {
165 | if ((strcasecmp(((Field *)item)->field_name, value) == 0) &&
166 | ((table == NULL) ||
167 | (strcasecmp(*((Field *)item)->table_name, table) == 0)))
168 | {
169 | j = i;
170 | found = true;
171 | }
172 | i++;
173 | }
174 | DBUG_RETURN(j);
175 | }
176 |
177 | /*
178 | Hide Attribute
179 |
180 | SYNOPSIS
181 | hide_attribute()
182 | int num IN the number of attribute to hide.
183 |
184 | DESCRIPTION
185 | This method sets the hidden property of the attribute to specify
186 | that the attribute is not to be sent to the client (used internally)
187 | by the optimizer.
188 |
189 | RETURN VALUE
190 | Success = 0
191 | Failed = -1
192 | */
193 | int Attribute::hide_attribute(Item *item, bool hide)
194 | {
195 | int i;
196 | DBUG_ENTER("hide_attribute");
197 | i = index_of((char *)*((Field *)item)->table_name,
198 | (char *)((Field *)item)->field_name);
199 | if (i > -1)
200 | hidden[i] = hide;
201 | DBUG_RETURN(0);
202 | }
203 |
204 | /*
205 | Get string value of attributes
206 |
207 | SYNOPSIS
208 | to_string()
209 |
210 | DESCRIPTION
211 | This method returns a formatted string of the attributes in the list.
212 |
213 | RETURN VALUE
214 | Success = char *
215 | Failed = ""
216 | */
217 | char *Attribute::to_string()
218 | {
219 | List_iterator
- it(attr_list);
220 | char *str = (char *)my_malloc(1024, MYF(MY_ZEROFILL | MY_WME));
221 | Item *item;
222 | int j = 0;
223 |
224 | DBUG_ENTER("to_string");
225 | strcpy(str, "");
226 | while ((item = it++))
227 | {
228 | if (j)
229 | strcat(str, ", ");
230 | if (*((Field *)item)->table_name)
231 | {
232 | strcat(str, *((Field *)item)->table_name);
233 | strcat(str, ".");
234 | }
235 | strcat(str, ((Field *)item)->field_name);
236 | if (!j)
237 | j = 1;
238 | }
239 | DBUG_RETURN(str);
240 | }
241 |
--------------------------------------------------------------------------------
/Ch14/attribute.h:
--------------------------------------------------------------------------------
1 | #include "sql_priv.h"
2 | #include "sql_class.h"
3 | #include "table.h"
4 |
5 | class Attribute
6 | {
7 | public:
8 | Attribute(void);
9 | int remove_attribute(int num);
10 | Item *get_attribute(int num);
11 | int add_attribute(bool append, Item *new_item);
12 | int num_attributes();
13 | int index_of(char *table, char *value);
14 | int hide_attribute(Item *item, bool hide);
15 | char *to_string();
16 | private:
17 | List
- attr_list;
18 | bool hidden[256];
19 | };
20 |
--------------------------------------------------------------------------------
/Ch14/ch14.result:
--------------------------------------------------------------------------------
1 | DROP DATABASE IF EXISTS expert_mysql;
2 | Warnings:
3 | Note 1008 Can't drop database 'expert_mysql'; database doesn't exist
4 | CREATE DATABASE expert_mysql;
5 | USE expert_mysql;
6 | CREATE TABLE `building` (
7 | `dir_code` char(4) NOT NULL,
8 | `building` char(6) NOT NULL
9 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
10 | CREATE TABLE `directorate` (
11 | `dir_code` char(4) NOT NULL,
12 | `dir_name` char(30) DEFAULT NULL,
13 | `dir_head_id` char(9) DEFAULT NULL,
14 | PRIMARY KEY (`dir_code`)
15 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
16 | CREATE TABLE `staff` (
17 | `id` char(9) NOT NULL,
18 | `first_name` char(20) DEFAULT NULL,
19 | `mid_name` char(20) DEFAULT NULL,
20 | `last_name` char(30) DEFAULT NULL,
21 | `sex` char(1) DEFAULT NULL,
22 | `salary` int(11) DEFAULT NULL,
23 | `mgr_id` char(9) DEFAULT NULL,
24 | PRIMARY KEY (`id`)
25 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
26 | CREATE TABLE `tasking` (
27 | `id` char(9) NOT NULL,
28 | `project_number` char(9) NOT NULL,
29 | `hours_worked` double DEFAULT NULL
30 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
31 | USE expert_mysql;
32 | INSERT INTO expert_mysql.building VALUES ('N41', '1300');
33 | INSERT INTO expert_mysql.building VALUES ('N01', '1453');
34 | INSERT INTO expert_mysql.building VALUES ('M00', '1000');
35 | INSERT INTO expert_mysql.building VALUES ('N41', '1301');
36 | INSERT INTO expert_mysql.building VALUES ('N41', '1305');
37 | INSERT INTO expert_mysql.directorate VALUES ('N41', 'Development', '333445555');
38 | INSERT INTO expert_mysql.directorate VALUES ('N01', 'Human Resources', '123654321');
39 | INSERT INTO expert_mysql.directorate VALUES ('M00', 'Management', '333444444');
40 | INSERT INTO expert_mysql.staff VALUES ('333445555', 'John', 'Q', 'Smith', 'M', 30000, '333444444');
41 | INSERT INTO expert_mysql.staff VALUES ('123763153', 'William', 'E', 'Walters', 'M', 25000, '123654321');
42 | INSERT INTO expert_mysql.staff VALUES ('333444444', 'Alicia', 'F', 'St.Cruz', 'F', 25000, 'None');
43 | INSERT INTO expert_mysql.staff VALUES ('921312388', 'Goy', 'X', 'Hong', 'F', 40000, '123654321');
44 | INSERT INTO expert_mysql.staff VALUES ('800122337', 'Rajesh', 'G', 'Kardakarna', 'M', 38000, '333445555');
45 | INSERT INTO expert_mysql.staff VALUES ('820123637', 'Monty', 'C', 'Smythe', 'M', 38000, '333445555');
46 | INSERT INTO expert_mysql.staff VALUES ('830132335', 'Richard', 'E', 'Jones', 'M', 38000, '333445555');
47 | INSERT INTO expert_mysql.staff VALUES ('333445665', 'Edward', 'E', 'Engles', 'M', 25000, '333445555');
48 | INSERT INTO expert_mysql.staff VALUES ('123654321', 'Beware', 'D', 'Borg', 'F', 55000, '333444444');
49 | INSERT INTO expert_mysql.staff VALUES ('123456789', 'Wilma', 'N', 'Maxima', 'F', 43000, '333445555');
50 | INSERT INTO expert_mysql.tasking VALUES ('333445555', '405', 23);
51 | INSERT INTO expert_mysql.tasking VALUES ('123763153', '405', 33.5);
52 | INSERT INTO expert_mysql.tasking VALUES ('921312388', '601', 44);
53 | INSERT INTO expert_mysql.tasking VALUES ('800122337', '300', 13);
54 | INSERT INTO expert_mysql.tasking VALUES ('820123637', '300', 9.5);
55 | INSERT INTO expert_mysql.tasking VALUES ('830132335', '401', 8.5);
56 | INSERT INTO expert_mysql.tasking VALUES ('333445555', '300', 11);
57 | INSERT INTO expert_mysql.tasking VALUES ('921312388', '500', 13);
58 | INSERT INTO expert_mysql.tasking VALUES ('800122337', '300', 44);
59 | INSERT INTO expert_mysql.tasking VALUES ('820123637', '401', 500.5);
60 | INSERT INTO expert_mysql.tasking VALUES ('830132335', '400', 12);
61 | INSERT INTO expert_mysql.tasking VALUES ('333445665', '600', 300.25);
62 | INSERT INTO expert_mysql.tasking VALUES ('123654321', '607', 444.75);
63 | INSERT INTO expert_mysql.tasking VALUES ('123456789', '300', 1000);
64 | DBXP_SELECT first_name, last_name, sex, id FROM staff;
65 | first_name last_name sex id
66 | John Smith M 333445555
67 | William Walters M 123763153
68 | Alicia St.Cruz F 333444444
69 | Goy Hong F 921312388
70 | Rajesh Kardakarna M 800122337
71 | Monty Smythe M 820123637
72 | Richard Jones M 830132335
73 | Edward Engles M 333445665
74 | Beware Borg F 123654321
75 | Wilma Maxima F 123456789
76 | DBXP_SELECT id FROM staff;
77 | id
78 | 333445555
79 | 123763153
80 | 333444444
81 | 921312388
82 | 800122337
83 | 820123637
84 | 830132335
85 | 333445665
86 | 123654321
87 | 123456789
88 | DBXP_SELECT dir_name FROM directorate;
89 | dir_name
90 | Development
91 | Human Resources
92 | Management
93 | DBXP_SELECT id, dir_name FROM staff
94 | JOIN directorate ON staff.mgr_id = directorate.dir_head_id;
95 | id dir_name
96 | 123763153 Human Resources
97 | 921312388 Human Resources
98 | 333445555 Management
99 | 123654321 Management
100 | 800122337 Development
101 | 820123637 Development
102 | 830132335 Development
103 | 333445665 Development
104 | 123456789 Development
105 | DBXP_SELECT id, dir_name FROM staff, directorate
106 | WHERE staff.mgr_id = directorate.dir_head_id;
107 | id dir_name
108 | 123763153 Human Resources
109 | 921312388 Human Resources
110 | 333445555 Management
111 | 123654321 Management
112 | 800122337 Development
113 | 820123637 Development
114 | 830132335 Development
115 | 333445665 Development
116 | 123456789 Development
117 | DBXP_SELECT * FROM staff WHERE staff.id = '123456789';
118 | id first_name mid_name last_name sex salary mgr_id
119 | 123456789 Wilma N Maxima F 43000 333445555
120 | DBXP_SELECT first_name, last_name FROM staff join directorate ON staff.mgr_id = directorate.dir_head_id
121 | WHERE directorate.dir_code = 'N41';
122 | first_name last_name
123 | Rajesh Kardakarna
124 | Monty Smythe
125 | Richard Jones
126 | Edward Engles
127 | Wilma Maxima
128 | DBXP_SELECT * FROM directorate JOIN building ON directorate.dir_code = building.dir_code;
129 | dir_code dir_name dir_head_id dir_code building
130 | M00 Management 333444444 M00 1000
131 | N01 Human Resources 123654321 N01 1453
132 | N41 Development 333445555 N41 1300
133 | N41 Development 333445555 N41 1301
134 | N41 Development 333445555 N41 1305
135 | DBXP_SELECT directorate.dir_code, dir_name, building, dir_head_id
136 | FROM directorate JOIN building ON directorate.dir_code = building.dir_code;
137 | dir_code dir_name building dir_head_id
138 | M00 Management 1000 333444444
139 | N01 Human Resources 1453 123654321
140 | N41 Development 1300 333445555
141 | N41 Development 1301 333445555
142 | N41 Development 1305 333445555
143 | DROP DATABASE expert_mysql;
144 |
--------------------------------------------------------------------------------
/Ch14/ch14.test:
--------------------------------------------------------------------------------
1 | #
2 | # Sample test to test the DBXP_SELECT execution
3 | #
4 |
5 | --source include/ch14.sql
6 |
7 | # Test 1:
8 | DBXP_SELECT first_name, last_name, sex, id FROM staff;
9 |
10 | # Test 2:
11 | DBXP_SELECT id FROM staff;
12 |
13 | # Test 3:
14 | DBXP_SELECT dir_name FROM directorate;
15 |
16 | # Test 4a:
17 | DBXP_SELECT id, dir_name FROM staff
18 | JOIN directorate ON staff.mgr_id = directorate.dir_head_id;
19 |
20 | # Test 4b:
21 | DBXP_SELECT id, dir_name FROM staff, directorate
22 | WHERE staff.mgr_id = directorate.dir_head_id;
23 |
24 | # Test 5:
25 | DBXP_SELECT * FROM staff WHERE staff.id = '123456789';
26 |
27 | # Test 6:
28 | DBXP_SELECT first_name, last_name FROM staff join directorate ON staff.mgr_id = directorate.dir_head_id
29 | WHERE directorate.dir_code = 'N41';
30 |
31 | # Test 7:
32 | DBXP_SELECT * FROM directorate JOIN building ON directorate.dir_code = building.dir_code;
33 |
34 | # Test 8:
35 | DBXP_SELECT directorate.dir_code, dir_name, building, dir_head_id
36 | FROM directorate JOIN building ON directorate.dir_code = building.dir_code;
37 |
38 | DROP DATABASE expert_mysql;
39 |
--------------------------------------------------------------------------------
/Ch14/ch14.txt:
--------------------------------------------------------------------------------
1 |
2 | mysql> DBXP_SELECT first_name, last_name, sex, id FROM staf' at line 1
3 | +------------+------------+------+-----------+
4 | | first_name | last_name | sex | id |
5 | +------------+------------+------+-----------+
6 | | John | Smith | M | 333445555 |
7 | | William | Walters | M | 123763153 |
8 | | Alicia | St.Cruz | F | 333444444 |
9 | | Goy | Hong | F | 921312388 |
10 | | Rajesh | Kardakarna | M | 800122337 |
11 | | Monty | Smythe | M | 820123637 |
12 | | Richard | Jones | M | 830132335 |
13 | | Edward | Engles | M | 333445665 |
14 | | Beware | Borg | F | 123654321 |
15 | | Wilma | Maxima | F | 123456789 |
16 | +------------+------------+------+-----------+
17 | 10 rows in set (0.01 sec)
18 |
19 | mysql> DBXP_SELECT id FROM staff;
20 | +-----------+
21 | | id |
22 | +-----------+
23 | | 333445555 |
24 | | 123763153 |
25 | | 333444444 |
26 | | 921312388 |
27 | | 800122337 |
28 | | 820123637 |
29 | | 830132335 |
30 | | 333445665 |
31 | | 123654321 |
32 | | 123456789 |
33 | +-----------+
34 | 10 rows in set (0.00 sec)
35 |
36 | mysql> DBXP_SELECT dir_name FROM directorate;
37 | +-----------------+
38 | | dir_name |
39 | +-----------------+
40 | | Development |
41 | | Human Resources |
42 | | Management |
43 | +-----------------+
44 | 3 rows in set (0.00 sec)
45 |
46 | mysql> DBXP_SELECT id, dir_name FROM staff
47 | JOIN directorate ON staff.mgr_id = directorate.dir_head_id;
48 | +-----------+-----------------+
49 | | id | dir_name |
50 | +-----------+-----------------+
51 | | 123763153 | Human Resources |
52 | | 921312388 | Human Resources |
53 | | 333445555 | Management |
54 | | 123654321 | Management |
55 | | 800122337 | Development |
56 | | 820123637 | Development |
57 | | 830132335 | Development |
58 | | 333445665 | Development |
59 | | 123456789 | Development |
60 | +-----------+-----------------+
61 | 9 rows in set (0.00 sec)
62 |
63 | mysql> DBXP_SELECT id, dir_name FROM staff, directorate
64 | WHERE staff.mgr_id = directorate.dir_head_id;
65 | +-----------+-----------------+
66 | | id | dir_name |
67 | +-----------+-----------------+
68 | | 123763153 | Human Resources |
69 | | 921312388 | Human Resources |
70 | | 333445555 | Management |
71 | | 123654321 | Management |
72 | | 800122337 | Development |
73 | | 820123637 | Development |
74 | | 830132335 | Development |
75 | | 333445665 | Development |
76 | | 123456789 | Development |
77 | +-----------+-----------------+
78 | 9 rows in set (0.00 sec)
79 |
80 | mysql> DBXP_SELECT * FROM staff WHERE staff.id = '123456789';
81 | +-----------+------------+----------+-----------+------+--------+-----------+
82 | | id | first_name | mid_name | last_name | sex | salary | mgr_id |
83 | +-----------+------------+----------+-----------+------+--------+-----------+
84 | | 123456789 | Wilma | N | Maxima | F | 43000 | 333445555 |
85 | +-----------+------------+----------+-----------+------+--------+-----------+
86 | 1 row in set (0.00 sec)
87 |
88 | mysql> DBXP_SELECT first_name, last_name FROM staff join directorate ON staff.mgr_id = directorate.dir_head_id WHERE directorate.dir_code = 'N41';
89 | +------------+------------+
90 | | first_name | last_name |
91 | +------------+------------+
92 | | Rajesh | Kardakarna |
93 | | Monty | Smythe |
94 | | Richard | Jones |
95 | | Edward | Engles |
96 | | Wilma | Maxima |
97 | +------------+------------+
98 | 5 rows in set (0.00 sec)
99 |
100 | mysql> DBXP_SELECT * FROM directorate JOIN building ON directorate.dir_code = building.dir_code;
101 | +----------+-----------------+-------------+----------+----------+
102 | | dir_code | dir_name | dir_head_id | dir_code | building |
103 | +----------+-----------------+-------------+----------+----------+
104 | | M00 | Management | 333444444 | M00 | 1000 |
105 | | N01 | Human Resources | 123654321 | N01 | 1453 |
106 | | N41 | Development | 333445555 | N41 | 1300 |
107 | | N41 | Development | 333445555 | N41 | 1301 |
108 | | N41 | Development | 333445555 | N41 | 1305 |
109 | +----------+-----------------+-------------+----------+----------+
110 | 5 rows in set (0.00 sec)
111 |
112 | mysql> DBXP_SELECT directorate.dir_code, dir_name, building, dir_head_id
113 | FROM directorate JOIN building ON directorate.dir_code = building.dir_code;
114 | +----------+-----------------+----------+-------------+
115 | | dir_code | dir_name | building | dir_head_id |
116 | +----------+-----------------+----------+-------------+
117 | | M00 | Management | 1000 | 333444444 |
118 | | N01 | Human Resources | 1453 | 123654321 |
119 | | N41 | Development | 1300 | 333445555 |
120 | | N41 | Development | 1301 | 333445555 |
121 | | N41 | Development | 1305 | 333445555 |
122 | +----------+-----------------+----------+-------------+
123 | 5 rows in set (0.00 sec)
124 |
125 | mysql>
126 |
--------------------------------------------------------------------------------
/Ch14/expression.h:
--------------------------------------------------------------------------------
1 | #include "sql_priv.h"
2 | #include "sql_class.h"
3 | #include "table.h"
4 | #include
5 |
6 | struct expr_node
7 | {
8 | Item *left_op;
9 | Item *operation;
10 | Item *right_op;
11 | Item *junction;
12 | expr_node *next;
13 | };
14 |
15 | class Expression
16 | {
17 | public:
18 | Expression(void);
19 | int remove_expression(int num, bool free);
20 | expr_node *get_expression(int num);
21 | int add_expression(bool append, expr_node *new_item);
22 | int num_expressions();
23 | int index_of(char *table, char *value);
24 | int reduce_expressions(TABLE *table);
25 | bool has_table(char *table);
26 | int convert(THD *thd, Item *mysql_expr);
27 | char *to_string();
28 | bool evaluate(TABLE *table1);
29 | int compare_join(expr_node *expr, TABLE *t1, TABLE *t2);
30 | int get_join_expr(Expression *where_expr);
31 | private:
32 | expr_node *root;
33 | Field *find_field(TABLE *tbl, char *name);
34 | bool compare(expr_node *expr, TABLE *t1);
35 | int num_expr;
36 | };
37 |
--------------------------------------------------------------------------------
/Ch14/query_tree.h:
--------------------------------------------------------------------------------
1 | /*
2 | Query_tree.h
3 |
4 | DESCRIPTION
5 | This file contains the Query_tree class. It is responsible for containing the
6 | internal representation of the query to be executed. It provides methods for
7 | optimizing and forming and inspecting the query tree. This class is the very
8 | heart of the DBXP query capability! It also provides the ability to store
9 | a binary "compiled" form of the query.
10 |
11 | NOTES
12 | The data structure is a binary tree that can have 0, 1, or 2 children. Only
13 | Join operations can have 2 children. All other operations have 0 or 1
14 | children. Each node in the tree is an operation and the links to children
15 | are the pipeline.
16 |
17 | SEE ALSO
18 | query_tree.cc
19 | */
20 | #include "attribute.h"
21 | #include "expression.h"
22 | #include "sql_priv.h"
23 | #include "sql_class.h"
24 | #include "table.h"
25 | #include "records.h"
26 |
27 | const int MAXNODETABLES = 4;
28 | const int LEFTCHILD = 0;
29 | const int RIGHTCHILD = 1;
30 |
31 | class Query_tree
32 | {
33 | public:
34 | enum query_node_type //this enumeration lists the available
35 | { //query node (operations)
36 | qntUndefined = 0,
37 | qntRestrict = 1,
38 | qntProject = 2,
39 | qntJoin = 3,
40 | qntSort = 4,
41 | qntDistinct = 5
42 | };
43 |
44 | enum join_con_type //this enumeration lists the available
45 | { //join operations supported
46 | jcUN = 0,
47 | jcNA = 1,
48 | jcON = 2,
49 | jcUS = 3
50 | };
51 |
52 | enum type_join //this enumeration lists the available
53 | { //join types supported.
54 | jnUNKNOWN = 0, //undefined
55 | jnINNER = 1,
56 | jnLEFTOUTER = 2,
57 | jnRIGHTOUTER = 3,
58 | jnFULLOUTER = 4,
59 | jnCROSSPRODUCT = 5,
60 | jnUNION = 6,
61 | jnINTERSECT = 7
62 | };
63 |
64 | enum AggregateType //used to add aggregate functions
65 | {
66 | atNONE = 0,
67 | atCOUNT = 1
68 | };
69 |
70 | /*
71 | STRUCTURE query_node
72 |
73 | DESCRIPTION
74 | This this structure contains all of the data for a query node:
75 |
76 | NodeId -- the internal id number for a node
77 | ParentNodeId -- the internal id for the parent node (used for insert)
78 | SubQuery -- is this the start of a subquery?
79 | Child -- is this a Left or Right child of the parent?
80 | NodeType -- synonymous with operation type
81 | JoinType -- if a join, this is the join operation
82 | join_con_type -- if this is a join, this is the "on" condition
83 | Expressions -- the expressions from the "where" clause for this node
84 | Join Expressions -- the join expressions from the "join" clause(s)
85 | Relations[] -- the relations for this operation (at most 2)
86 | PreemptPipeline -- does the pipeline need to be halted for a sort?
87 | Fields -- the attributes for the result set of this operation
88 | Left -- a pointer to the left child node
89 | Right -- a pointer to the right child node
90 | */
91 | struct query_node
92 | {
93 | query_node();
94 | ~query_node();
95 | int nodeid;
96 | int parent_nodeid;
97 | bool sub_query;
98 | int child;
99 | query_node_type node_type;
100 | type_join join_type;
101 | join_con_type join_cond;
102 | Expression *where_expr;
103 | Expression *join_expr;
104 | TABLE_LIST *relations[MAXNODETABLES];
105 | int eof[MAXNODETABLES];
106 | int ndx[MAXNODETABLES];
107 | bool preempt_pipeline;
108 | Attribute *attributes;
109 | query_node *left;
110 | query_node *right;
111 | };
112 |
113 | struct record_buff
114 | {
115 | uchar *field_ptr;
116 | long field_length;
117 | record_buff *next;
118 | record_buff *prev;
119 | READ_RECORD *record;
120 | };
121 |
122 | query_node *root; //The ROOT node of the tree
123 |
124 | Query_tree(void);
125 | ~Query_tree(void);
126 | int init_node(query_node *qn);
127 | int heuristic_optimization();
128 | int cost_optimization();
129 | int insert_attribute(query_node *qn, Item *c);
130 | bool distinct;
131 | int prepare(query_node *qn);
132 | int cleanup(query_node *qn);
133 | bool Eof(query_node *qn);
134 | READ_RECORD *get_next(query_node *qn);
135 | List
- result_fields;
136 |
137 | private:
138 | bool h_opt; //has query been optimized (rules)?
139 | bool c_opt; //has query been optimized (cost)?
140 | READ_RECORD *lbuff;
141 | READ_RECORD *rbuff;
142 | record_buff *left_record_buff;
143 | record_buff *right_record_buff;
144 | record_buff *left_record_buffer_ptr;
145 | record_buff *right_record_buffer_ptr;
146 |
147 | int push_projections(query_node *qn, query_node *pNode);
148 | query_node *find_projection(query_node *qn);
149 | bool is_leaf(query_node *qn);
150 | bool has_relation(query_node *qn, char *Table);
151 | bool has_attribute(query_node *qn, Item *a);
152 | int del_attribute(query_node *qn, Item *a);
153 | int push_restrictions(query_node *qn, query_node *pNode);
154 | query_node *find_restriction(query_node *qn);
155 | query_node *find_join(query_node *qn);
156 | int push_joins(query_node *qn, query_node *pNode);
157 | int prune_tree(query_node *prev, query_node *cur_node);
158 | int balance_joins(query_node *qn);
159 | int split_restrict_with_project(query_node *qn);
160 | int split_restrict_with_join(query_node *qn);
161 | int split_project_with_join(query_node *qn);
162 | bool find_table_in_tree(query_node *qn, char *tbl);
163 | bool find_table_in_expr(Expression *expr, char *tbl);
164 | bool find_attr_in_expr(Expression *expr, char *tbl, char *value);
165 | int apply_indexes(query_node *qn);
166 | bool do_restrict(query_node *qn, READ_RECORD *t);
167 | READ_RECORD *do_project(query_node *qn, READ_RECORD *t);
168 | READ_RECORD *do_join(query_node *qn);
169 | int find_index_in_expr(Expression *e, char *tbl);
170 | TABLE *get_table(query_node *qn);
171 | int insertion_sort(bool left, Field *field, READ_RECORD *rcd);
172 | int check_rewind(record_buff *cur_left, record_buff *curr_left_prev,
173 | record_buff *cur_right, record_buff *cur_right_prev);
174 | };
175 |
--------------------------------------------------------------------------------
/Ch14/source_Ch14.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Ch14/source_Ch14.zip
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/LICENSE.txt
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apress Source Code
2 |
3 | This repository accompanies [*Expert MySQL*](http://www.apress.com/9781430246596) by Charles Bell (Apress, 2012).
4 |
5 | 
6 |
7 | Download the files as a zip using the green button, or clone the repository to your machine using Git.
8 |
9 | ## Releases
10 |
11 | Release v1.0 corresponds to the code in the published book, without corrections or updates.
12 |
13 | ## Contributions
14 |
15 | See the file Contributing.md for more information on how you can contribute to this repository.
16 |
--------------------------------------------------------------------------------
/Sample_data/bvm_data.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Sample_data/bvm_data.sql
--------------------------------------------------------------------------------
/Sample_data/bvm_images.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Apress/exp-mysql-12/37d3034e259d682b8c7d141699acc706eb8b6271/Sample_data/bvm_images.zip
--------------------------------------------------------------------------------
/Sample_data/sample_data.sql:
--------------------------------------------------------------------------------
1 | -- MySQL dump 10.10
2 | --
3 | -- Host: localhost Database: expert_mysql
4 | -- ------------------------------------------------------
5 | -- Server version 5.1.9-beta-debug-DBXP 1.0
6 |
7 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
8 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
9 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
10 | /*!40101 SET NAMES utf8 */;
11 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
12 | /*!40103 SET TIME_ZONE='+00:00' */;
13 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
14 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0
15 | */;
16 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
17 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
18 |
19 | CREATE DATABASE IF NOT EXISTS expert_mysql;
20 |
21 | --
22 | -- Table structure for table `expert_mysql`.`building`
23 | --
24 |
25 | DROP TABLE IF EXISTS `expert_mysql`.`building`;
26 | CREATE TABLE `expert_mysql`.`building` (
27 | `dir_code` char(4) NOT NULL,
28 | `building` char(6) NOT NULL
29 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
30 |
31 | --
32 | -- Dumping data for table `expert_mysql`.`building`
33 | --
34 |
35 |
36 | /*!40000 ALTER TABLE `expert_mysql`.`building` DISABLE KEYS */;
37 | LOCK TABLES `expert_mysql`.`building` WRITE;
38 | INSERT INTO `expert_mysql`.`building` VALUES
39 | ('N41','1300'),
40 | ('N01','1453'),
41 | ('M00','1000'),
42 | ('N41','1301'),
43 | ('N41','1305');
44 | UNLOCK TABLES;
45 | /*!40000 ALTER TABLE `expert_mysql`.`building` ENABLE KEYS */;
46 |
47 | --
48 | -- Table structure for table `expert_mysql`.`directorate`
49 | --
50 |
51 | DROP TABLE IF EXISTS `expert_mysql`.`directorate`;
52 | CREATE TABLE `expert_mysql`.`directorate` (
53 | `dir_code` char(4) NOT NULL,
54 | `dir_name` char(30) DEFAULT NULL,
55 | `dir_head_id` char(9) DEFAULT NULL,
56 | PRIMARY KEY (`dir_code`)
57 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
58 |
59 | --
60 | -- Dumping data for table `expert_mysql`.`directorate`
61 | --
62 |
63 |
64 | /*!40000 ALTER TABLE `expert_mysql`.`directorate` DISABLE KEYS */;
65 | LOCK TABLES `expert_mysql`.`directorate` WRITE;
66 | INSERT INTO `expert_mysql`.`directorate` VALUES
67 | ('N41','Development','333445555'),
68 | ('N01','Human Resources','123654321'),
69 | ('M00','Management','333444444');
70 | UNLOCK TABLES;
71 | /*!40000 ALTER TABLE `directorate` ENABLE KEYS */;
72 |
73 | --
74 | -- Table structure for table `expert_mysql`.`staff`
75 | --
76 |
77 | DROP TABLE IF EXISTS `expert_mysql`.`staff`;
78 | CREATE TABLE `expert_mysql`.`staff` (
79 | `id` char(9) NOT NULL,
80 | `first_name` char(20) DEFAULT NULL,
81 | `mid_name` char(20) DEFAULT NULL,
82 | `last_name` char(30) DEFAULT NULL,
83 | `sex` char(1) DEFAULT NULL,
84 | `salary` int(11) DEFAULT NULL,
85 | `mgr_id` char(9) DEFAULT NULL,
86 | PRIMARY KEY (`id`)
87 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
88 |
89 | --
90 | -- Dumping data for table `expert_mysql`.`staff`
91 | --
92 |
93 |
94 | /*!40000 ALTER TABLE `expert_mysql`.`staff` DISABLE KEYS */;
95 | LOCK TABLES `expert_mysql`.`staff` WRITE;
96 | INSERT INTO `expert_mysql`.`staff` VALUES
97 | ('333445555','John','Q','Smith','M',30000,'333444444'),
98 | ('123763153','William','E','Walters','M',25000,'123654321'),
99 | ('333444444','Alicia','F','St.Cruz','F',25000,NULL),
100 | ('921312388','Goy','X','Hong','F',40000,'123654321'),
101 | ('800122337','Rajesh','G','Kardakarna','M',38000,'333445555'),
102 | ('820123637','Monty','C','Smythe','M',38000,'333445555'),
103 | ('830132335','Richard','E','Jones','M',38000,'333445555'),
104 | ('333445665','Edward','E','Engles','M',25000,'333445555'),
105 | ('123654321','Beware','D','Borg','F',55000,'333444444'),
106 | ('123456789','Wilma','N','Maxima','F',43000,'333445555');
107 | UNLOCK TABLES;
108 | /*!40000 ALTER TABLE `expert_mysql`.`staff` ENABLE KEYS */;
109 |
110 | --
111 | -- Table structure for table `tasking`
112 | --
113 |
114 | DROP TABLE IF EXISTS `expert_mysql`.`tasking`;
115 | CREATE TABLE `expert_mysql`.`tasking` (
116 | `id` char(9) NOT NULL,
117 | `project_number` char(9) NOT NULL,
118 | `hours_worked` double DEFAULT NULL
119 | ) ENGINE=MyISAM DEFAULT CHARSET=latin1;
120 |
121 | --
122 | -- Dumping data for table `tasking`
123 | --
124 |
125 |
126 | /*!40000 ALTER TABLE `tasking` DISABLE KEYS */;
127 | LOCK TABLES `expert_mysql`.`tasking` WRITE;
128 | INSERT INTO `expert_mysql`.`tasking` VALUES
129 | ('333445555','405',23),
130 | ('123763153','405',33.5),
131 | ('921312388','601',44),
132 | ('800122337','300',13),
133 | ('820123637','300',9.5),
134 | ('830132335','401',8.5),
135 | ('333445555','300',11),
136 | ('921312388','500',13),
137 | ('800122337','300',44),
138 | ('820123637','401',500.5),
139 | ('830132335','400',12),
140 | ('333445665','600',300.25),
141 | ('123654321','607',444.75),
142 | ('123456789','300',1000);
143 | UNLOCK TABLES;
144 | /*!40000 ALTER TABLE `expert_mysql`.`tasking` ENABLE KEYS */;
145 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
146 |
147 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
148 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
149 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
150 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
151 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
152 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
153 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
154 |
--------------------------------------------------------------------------------
/contributing.md:
--------------------------------------------------------------------------------
1 | # Contributing to Apress Source Code
2 |
3 | Copyright for Apress source code belongs to the author(s). However, under fair use you are encouraged to fork and contribute minor corrections and updates for the benefit of the author(s) and other readers.
4 |
5 | ## How to Contribute
6 |
7 | 1. Make sure you have a GitHub account.
8 | 2. Fork the repository for the relevant book.
9 | 3. Create a new branch on which to make your change, e.g.
10 | `git checkout -b my_code_contribution`
11 | 4. Commit your change. Include a commit message describing the correction. Please note that if your commit message is not clear, the correction will not be accepted.
12 | 5. Submit a pull request.
13 |
14 | Thank you for your contribution!
--------------------------------------------------------------------------------