Archive for the ‘MySQL DBA’ tag
Bash Arrays & MySQL
Student questions are always interesting! They get me to think and to write. The question this time is: “How do I write a Bash Shell script to process multiple MySQL script files?” This post builds the following model (courtesy of MySQL Workbench) by using a bash shell script and MySQL script files, but there’s a disclaimer on this post. It shows both insecure and secure approaches and you should avoid the insecure ones.
It seems a quick refresher on how to use arrays in bash
shell may be helpful. While it’s essential in a Linux environment, it’s seems not everyone masters the bash
shell.
Especially, since I checked my Learning the Bash Shell (2nd Edition) and found a typo on how you handle arrays in the bash
shell, and it’s a mistake that could hang newbies up (on page 161). Perhaps I should update my copy because I bought it in 1998. 😉 It was good then, and the new edition is probably better. The error is probably corrected in the current Learning the Bash Shell, but if not, the following examples show you how to use arrays in loops.
Naturally, these do presume some knowledge of working with bash
shell, like the first line always is the same in any bash
shell script. That you open an if-statement with an if
and close it with a fi
, and that you else-if is elif
; and that a semicolon between a for-statement and the do
statement is required when they’re on the same line because they’re two statements.
If you’re new to bash
shell arrays, click on the link below to expand a brief tutorial. It takes you through three progressive examples of working with bash
arrays.
Working with bash
Arrays ↓
A basic example of working with an array in bash
shell is the following list1.sh
script:
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/bash # Print script name. echo $0 #!/usr/bin/bash # Define an array. declare -a cmd=("one" "two" "three") # Call the array elements. for i in ${cmd[*]}; do echo ${i} done |
Line 8 declares the cmd
array by assigning three strings. Line 12 returns the elements of the array to the ${i}
variable, which lets you manage them one at a time. You use the chmod
command to make the list1.sh
executable, like this:
chmod 755 list1.sh |
Then, you can run it like this from the present working directory (pwd
):
./list1.sh |
It should print:
one two three |
The list2.sh
example changes the cmd
array declaration from list1.sh
. It declares the cmd
array as an empty array, and then it assigns elements by index numbers (using a zero-based index), as shown below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/bash # Define an array. declare -a cmd # Assign elements to an array. cmd[0]="one" cmd[1]="two" cmd[2]="three" # Call the array elements. for i in ${cmd[*]}; do echo ${i} done |
Lines 7 through 9 assign values to the elements of the cmd
array. You would chmod
the file, and run the file as qualified above for the list1.sh
script.
The last pre-implementation example requires that you create three demonstration scripts, the one.sh
, two.sh
, and three.sh
scripts. You should put them in the same directory as the list3.sh
script.
The demonstration scripts should all have the same code, like this:
1 2 3 4 | #!/usr/bin/bash # Print script name. echo $0 |
Line 4 returns command line parameter $0
or ${0}
, which is always the command line program’s file name. The file name may be provided as a relative or absolute file name, and if that’s new to you please check out The Linux Command Line: A Complete Introduction (also downloadable as a PDF for free).
The list3.sh
script should contain the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/bash <code> # Define an array. declare -a cmd # Assign elements to an array. cmd[0]="one.sh" cmd[1]="two.sh" cmd[2]="three.sh" # Call the array elements. for i in ${cmd[*]}; do `pwd`/${i} done |
When you run the list3.sh
script from the /home/student/Code/bash directory with a local syntax, the script should return the fully qualified file names of the subshell programs. The output should look like this:
/home/student/Code/bash/one.sh /home/student/Code/bash/two.sh /home/student/Code/bash/three.sh |
The list3.sh
script provides the present working directory (pwd
) and the one.sh
, two.sh
, and three.sh
scripts return only their executable name. For example, if you ran one.sh
with the following syntax:
./one.sh |
It returns
./one.sh |
Only one more trick needs to be qualified before our main MySQL examples. That trick is how you pass parameters to a bash
shell script. For reference, this is the part that’s insecure because user command histories are available inside the Linux OS.
Here’s a hello_whom.sh
script to demonstrates the concept of parameter passing:
1 2 3 4 5 6 7 8 9 10 | #!/usr/bin/bash # This says hello to the argument while managing no argument. if [[ ${#} = 1 ]]; then echo 'The '${0}' program says: "Hello '${1}'!"' elif [[ ${#} > 1 ]]; then echo 'The '${0}' program wants to know if you have more than one name?' else echo 'The '${0}' program wants to know if you have a name?' fi |
If you need more on how parameters are passed and managed, you can check a prior blob post on Handling bash
Parameters, or check the bash help pages. The following leverages bash
arrays to run scripts and query the MySQL database from the command line.
You will need the three batch SQL files first, so here they are:
Setup SQL Files ↓
The actor.sql
file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | -- Use the sampledb database. USE sampledb; -- Disable foreign key checking. SET foreign_key_checks = 0; -- Drop an actor table. DROP TABLE IF EXISTS actor; -- Create an actor table. CREATE TABLE actor ( actor_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT , actor_name VARCHAR(30) NOT NULL ); -- Insert two rows. INSERT INTO actor (actor_name) VALUES ('Chris Hemsworth'); INSERT INTO actor (actor_name) VALUES ('Chris Pine'); INSERT INTO actor (actor_name) VALUES ('Chris Pratt'); |
The film.sql
file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | -- Use the sampledb database. USE sampledb; -- Disable foreign key checking. SET foreign_key_checks = 0; -- Drop a film table. DROP TABLE IF EXISTS film; -- Create a film table. CREATE TABLE film ( film_id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT , film_name VARCHAR(30) NOT NULL ); -- Insert rows. INSERT INTO film (film_name) VALUES ('Thor'); INSERT INTO film (film_name) VALUES ('Thor: The Dark World'); INSERT INTO film (film_name) VALUES ('Star Trek'); INSERT INTO film (film_name) VALUES ('Star Trek into Darkness'); INSERT INTO film (film_name) VALUES ('Guardians of the Galaxy'); |
The movie.sql
file:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 | -- Use the sampledb database. USE sampledb; -- Disable foreign key checking. SET foreign_key_checks = 0; -- Drop an movie table. DROP TABLE IF EXISTS movie; -- Create an movie table. CREATE TABLE movie ( movie_id int unsigned PRIMARY KEY AUTO_INCREMENT , actor_id int unsigned NOT NULL , film_id int unsigned NOT NULL , CONSTRAINT actor_fk FOREIGN KEY (actor_id) REFERENCES actor (actor_id) , CONSTRAINT film_fk FOREIGN KEY (film_id) REFERENCES film(film_id)); -- Use scalar subqueries to discover surrogate keys by using the faux natural key. INSERT INTO movie ( actor_id , film_id ) VALUES ((SELECT actor_id FROM actor WHERE actor_name = 'Chris Hemsworth') ,(SELECT film_id FROM film WHERE film_name = 'Thor')); -- Use scalar subqueries to discover surrogate keys by using the faux natural key. INSERT INTO movie ( actor_id , film_id ) VALUES ((SELECT actor_id FROM actor WHERE actor_name = 'Chris Hemsworth') ,(SELECT film_id FROM film WHERE film_name = 'Thor: The Dark World')); -- Use scalar subqueries to discover surrogate keys by using the faux natural key. INSERT INTO movie ( actor_id , film_id ) VALUES ((SELECT actor_id FROM actor WHERE actor_name = 'Chris Pine') ,(SELECT film_id FROM film WHERE film_name = 'Star Trek')); -- Use scalar subqueries to discover surrogate keys by using the faux natural key. INSERT INTO movie ( actor_id , film_id ) VALUES ((SELECT actor_id FROM actor WHERE actor_name = 'Chris Pine') ,(SELECT film_id FROM film WHERE film_name = 'Star Trek into Darkness')); -- Use scalar subqueries to discover surrogate keys by using the faux natural key. INSERT INTO movie ( actor_id , film_id ) VALUES ((SELECT actor_id FROM actor WHERE actor_name = 'Chris Pratt') ,(SELECT film_id FROM film WHERE film_name = 'Guardians of the Galaxy')); |
The following list_mysql.sh
shell script expects to receive the username
, password
, database
and fully qualified path
in that specific order. The script names are entered manually because this should be a unit test script. Naturally, you can extend the script to manage those parameters but as mentioned I see this type of solution as a developer machine only script to simplify unit testing. Anything beyond that is risky!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | #!/usr/bin/bash # Assign user and password username="${1}" password="${2}" database="${3}" directory="${4}" # List the parameter values passed. echo "Username: " ${username} echo "Password: " ${password} echo "Database: " ${database} echo "Directory: " ${directory} echo "" # Define an array. declare -a cmd # Assign elements to an array. cmd[0]="actor.sql" cmd[1]="film.sql" cmd[2]="movie.sql" # Call the array elements. for i in ${cmd[*]}; do mysql -s -u${username} -p${password} -D${database} < ${directory}/${i} > /dev/null 2>/dev/null done # Connect and pipe the query result minus errors and warnings to the while loop. mysql -u${username} -p${password} -D${database} <<<'show tables' 2>/dev/null | # Read through the piped result until it's empty but format the title. while IFS='\n' read list; do if [[ ${list} = "Tables_in_sampledb" ]]; then echo $list echo "----------------------------------------" else echo $list fi done echo "" # Connect and pipe the query result minus errors and warnings to the while loop. mysql -u${username} -p${password} -D${database} <<<'SELECT CONCAT(a.actor_name," in ",f.film_name) AS "Actors in Films" FROM actor a INNER JOIN movie m ON a.actor_id = m.actor_id INNER JOIN film f ON m.film_id = f.film_id' 2>/dev/null | # Read through the piped result until it's empty but format the title. while IFS='\n' read actor_name; do if [[ ${actor_name} = "Actors in Films" ]]; then echo $actor_name echo "----------------------------------------" else echo $actor_name fi done |
The IFS
(Internal Field Separator) works with whitespace by default. The IFS
on lines 33 and 47 sets the IFS
to a line return ('\n'
). That’s the trick to display the data, and you can read more about the IFS
in this question and answer post.
You can run this script with the following input parameters from the local directory where you deploy it. The a parameters are: (1) username
, (2) password
, (3) database
, and (4) a fully qualified path to the SQL setup files.
./list_mysql.sh student student sampledb "/home/student/Code/bash/mysql" |
With valid input values, the list_mysql.sh
bash
script generates the following output, which confirms inputs and verifies actions taken by the scripts with queries:
Username: student Password: student Database: sampledb Directory: /home/student/Code/bash/mysql Tables_in_sampledb ---------------------------------------- actor film movie Actors in Films ---------------------------------------- Chris Hemsworth in Thor Chris Hemsworth in Thor: The Dark World Chris Pine in Star Trek Chris Pine in Star Trek into Darkness Chris Pine in Guardians of the Galaxy |
If you forgot to provide the required inputs to the list_mysql.sh
bash
script, it alternatively returns the following output:
Username: Password: Database: Directory: ./list_mysql.sh: line 25: /actor.sql: No such file or directory ./list_mysql.sh: line 25: /film.sql: No such file or directory ./list_mysql.sh: line 25: /movie.sql: No such file or directory |
The secure way removes the password at a minimum! The refactored program will require you to manually enter the password for all elements of the array (three in this sample), and twice for the two queries. Here’s the refactored code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | #!/usr/bin/bash # Assign user and password username="${1}" database="${2}" directory="${3}" # List the parameter values passed. echo "Username: " ${username} echo "Database: " ${database} echo "Directory: " ${directory} echo "" # Define an array. declare -a cmd # Assign elements to an array. cmd[0]="actor.sql" cmd[1]="film.sql" cmd[2]="movie.sql" # Call the array elements. for i in ${cmd[*]}; do mysql -s -u${username} -p -D${database} < ${directory}/${i} > /dev/null 2>/dev/null done # Connect and pipe the query result minus errors and warnings to the while loop. mysql -u${username} -p -D${database} <<<'show tables' 2>/dev/null | # Read through the piped result until it's empty. while IFS='\n' read list; do if [[ ${list} = "Tables_in_sampledb" ]]; then echo $list echo "----------------------------------------" else echo $list fi done echo "" # Connect and pipe the query result minus errors and warnings to the while loop. mysql -u${username} -p -D${database} <<<'SELECT CONCAT(a.actor_name," in ",f.film_name) AS "Actors in Films" FROM actor a INNER JOIN movie m ON a.actor_id = m.actor_id INNER JOIN film f ON m.film_id = f.film_id' 2>/dev/null | # Read through the piped result until it's empty. while IFS='\n' read actor_name; do if [[ ${actor_name} = "Actors in Films" ]]; then echo $actor_name echo "----------------------------------------" else echo $actor_name fi done |
Please let me know if you think there should be any more scaffolding for newbies in this post. As always, I hope this helps those looking for this type of solution.
MySQL OCP Exams
Planning out my year, I decided to take the Oracle OCP and MySQL OCP exams. I checked for review books and was pleasantly surprised to find the soon to be released OCP MySQL Database Administrator Exam Guide (Exam 1Z0-883). However, I noticed that the book was actually prepared for the obsolete and discountinued Exams 1Z0-870, 1Z0-873, and 1Z0-874. As it turns out, Steve O’Hearn has informed me that there isn’t a book and that the posting in Amazon.com is in error.
There isn’t an alternative review book for the OCP MySQL 5.6 Developer or Database Administrator Exams. The question that I have is simple: “How relevant is this book because it was prepared for the older exams?” There isn’t a table of content published on the Amazon.com site. If there was a table of contents it could help me determine how close the book’s content is to the new exam.
As a preparation to figure out the value of the book as a study guide, I’ve reviewed the current Oracle MySQL Training Objectives (listed below). The new MySQL OCP Developer and Administrator exams have the following descriptions and objectives:
- MySQL 5.6 Developer 1Z0-882. Oracle provides the following outline for their MySQL for Developer (Ed 3) training course:
Course Objectives
- Describe the MySQL client/server architecture
- Use MySQL client programs and common options
- Program MySQL applications with Java and PHP connectors
- Use a “NoSQL” approach to store and retrieve data
- Design efficient tables
- Create and delete database objects
- Use expressions in SQL statements
- Examine database metadata
- Use SQL statements to modify table data
- Maintain database integrity with transactions
- Write multiple table queries
- Create “virtual tables” containing specific data
- Create user-defined variables, prepared statements, and stored routines
- Create and manage triggers
- Identify and deal with errors and exceptions in client programs
- Write queries that are fast and effective, even under heavy loads
- MySQL 5.6 Database Administrator 1Z0-883. Oracle provides the following outline for their MySQL for Database Administrators (Ed 3.1) training course:
Course Objectives
- Describe the MySQL Architecture
- Install and Upgrade MySQL
- Use the INFORMATION_SCHEMA database to access metadata
- Perform the MySQL start and shutdown operations
- Configure MySQL server options at runtime
- Use available tools including MySQL Workbench
- Evaluate data types and character sets for performance issues
- Understand data locking in MySQL
- Understand the use of the InnoDB storage engine with MySQL
- Maintain integrity of a MySQL installation
- Use triggers for administration tasks
- Use Enterprise Audit and Pluggable Authentication
- Configure advanced replication topologies for high availability
- Describe introductory performance tuning techniques
- Perform backup and restore operations
- Automate administrative tasks with scheduled events
As always, I hope this helps those who read it; and, in this case I hope it helps you make an effective decision on preparation resources for the MySQL 5.6 OCP exams.
Ruby-MySQL Columns
Last week I posted how to configure and test Ruby and MySQL. Somebody asked me how to handle a dynamic list of columns. So, here’s a quick little program to show you how to read the dynamic list of column (and this updated blog post has the 2024 update for the new Mysql2 ODBC driver):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | require 'rubygems' require 'mysql' # Begin block. begin # Create a new connection resource. db = Mysql.new('localhost','student','student','studentdb') # Create a result set. rs = db.query('SELECT item_title, item_rating FROM item') # Read through the result set hash. rs.each do | row | out = "" i = 0 while i < db.field_count # Check if not last column. if i < db.field_count - 1 out += "#{row[i]}, " else out += "#{row[i]}" end i += 1 end puts "#{out}" end # Release the result set resources. rs.free rescue Mysql::Error => e # Print the error. puts "ERROR #{e.errno} (#{e.sqlstate}): #{e.error}" puts "Can't connect to MySQL database specified." # Signal an error. exit 1 ensure # Close the connection when it is open. db.close if db end |
The new logic on lines 13 through 22 reads the list of columns into a comma delimited list of values. The if
-block checks to make sure it doesn’t append a comma to the last column in the list. It prints output like:
The Hunt for Red October, PG Star Wars I, PG Star Wars II, PG Star Wars II, PG Star Wars III, PG13 The Chronicles of Narnia, PG RoboCop, Mature Pirates of the Caribbean, Teen The Chronicles of Narnia, Everyone MarioKart, Everyone Splinter Cell, Teen Need for Speed, Everyone The DaVinci Code, Teen Cars, Everyone Beau Geste, PG I Remember Mama, NR Tora! Tora! Tora!, G A Man for All Seasons, G Hook, PG Around the World in 80 Days, G Harry Potter and the Sorcerer's Stone, PG Camelot, G |
As always, I hope this helps those looking for a solution.
Java-MySQL Program
It turns out that configuring Perl wasn’t the last step for my student instance. It appears that I neglected to configure my student instance to support Java connectivity to MySQL. This post reviews the configuration of Java to run programs against MySQL. It also covers the new syntax on how you register a DriverManager
, and avoid Java compilation errors with the older syntax.
In prior posts, I’ve shown how to use Perl , PHP, Python, and Ruby languages to query a MySQL database on Linux.
You need to install the Open JDK libraries with the yum
utility command:
yum install -y java-1.7.0-openjdk* |
It should generate the following log output:
Loaded plugins: langpacks, refresh-packagekit Package 1:java-1.7.0-openjdk-1.7.0.75-2.5.4.2.fc20.x86_64 already installed and latest version Package 1:java-1.7.0-openjdk-headless-1.7.0.75-2.5.4.2.fc20.x86_64 already installed and latest version Resolving Dependencies --> Running transaction check ---> Package java-1.7.0-openjdk-accessibility.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed --> Processing Dependency: java-atk-wrapper for package: 1:java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.fc20.x86_64 ---> Package java-1.7.0-openjdk-demo.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed ---> Package java-1.7.0-openjdk-devel.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed ---> Package java-1.7.0-openjdk-javadoc.noarch 1:1.7.0.75-2.5.4.2.fc20 will be installed ---> Package java-1.7.0-openjdk-src.x86_64 1:1.7.0.75-2.5.4.2.fc20 will be installed --> Running transaction check ---> Package java-atk-wrapper.x86_64 0:0.30.4-4.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: java-1.7.0-openjdk-accessibility x86_64 1:1.7.0.75-2.5.4.2.fc20 updates 32 k java-1.7.0-openjdk-demo x86_64 1:1.7.0.75-2.5.4.2.fc20 updates 1.9 M java-1.7.0-openjdk-devel x86_64 1:1.7.0.75-2.5.4.2.fc20 updates 9.2 M java-1.7.0-openjdk-javadoc noarch 1:1.7.0.75-2.5.4.2.fc20 updates 14 M java-1.7.0-openjdk-src x86_64 1:1.7.0.75-2.5.4.2.fc20 updates 39 M Installing for dependencies: java-atk-wrapper x86_64 0.30.4-4.fc20 fedora 71 k Transaction Summary ================================================================================ Install 12 Packages (+1 Dependent package) Total download size: 163 M Installed size: 765 M Downloading packages: (1/6): java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.f | 32 kB 00:00 (2/6): java-1.7.0-openjdk-demo-1.7.0.75-2.5.4.2.fc20.x86_6 | 1.9 MB 00:02 (3/6): java-1.7.0-openjdk-devel-1.7.0.75-2.5.4.2.fc20.x86_ | 9.2 MB 00:05 (4/6): java-1.7.0-openjdk-javadoc-1.7.0.75-2.5.4.2.fc20.no | 14 MB 00:04 (5/6): java-atk-wrapper-0.30.4-4.fc20.x86_64.rpm | 71 kB 00:00 (6/6): java-1.7.0-openjdk-src-1.7.0.75-2.5.4.2.fc20.x86_6 | 39 MB 00:23 -------------------------------------------------------------------------------- Total 4.5 MB/s | 163 MB 00:36 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : java-atk-wrapper-0.30.4-4.fc20.x86_64 3/13 Installing : 1:java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.fc20 4/13 Installing : 1:java-1.7.0-openjdk-devel-1.7.0.75-2.5.4.2.fc20.x86_64 9/13 Installing : 1:java-1.7.0-openjdk-src-1.7.0.75-2.5.4.2.fc20.x86_64 10/13 Installing : 1:java-1.7.0-openjdk-javadoc-1.7.0.75-2.5.4.2.fc20.noarc 12/13 Installing : 1:java-1.7.0-openjdk-demo-1.7.0.75-2.5.4.2.fc20.x86_64 13/13 Verifying : 1:java-1.7.0-openjdk-demo-1.7.0.75-2.5.4.2.fc20.x86_64 2/13 Verifying : 1:java-1.7.0-openjdk-javadoc-1.7.0.75-2.5.4.2.fc20.noarc 3/13 Verifying : java-atk-wrapper-0.30.4-4.fc20.x86_64 5/13 Verifying : 1:java-1.7.0-openjdk-accessibility-1.7.0.75-2.5.4.2.fc20 6/13 Verifying : 1:java-1.7.0-openjdk-devel-1.7.0.75-2.5.4.2.fc20.x86_64 8/13 Verifying : 1:java-1.7.0-openjdk-src-1.7.0.75-2.5.4.2.fc20.x86_64 12/13 Installed: java-1.7.0-openjdk-accessibility.x86_64 1:1.7.0.75-2.5.4.2.fc20 java-1.7.0-openjdk-demo.x86_64 1:1.7.0.75-2.5.4.2.fc20 java-1.7.0-openjdk-devel.x86_64 1:1.7.0.75-2.5.4.2.fc20 java-1.7.0-openjdk-javadoc.noarch 1:1.7.0.75-2.5.4.2.fc20 java-1.7.0-openjdk-src.x86_64 1:1.7.0.75-2.5.4.2.fc20 Dependency Installed: java-atk-wrapper.x86_64 0:0.30.4-4.fc20 Complete! |
You can find the Java compiler’s version with the following command:
javac -version |
It should show you the following Java version:
javac 1.7.0_75 |
Next, you need to install the mysql-connector-java
library with yum
like this:
yum install -y mysql-connector-java |
It should generate the following installation output:
Loaded plugins: langpacks, refresh-packagekit mysql-connectors-community | 2.5 kB 00:00 mysql-tools-community | 2.5 kB 00:00 mysql56-community | 2.5 kB 00:00 pgdg93 | 3.6 kB 00:00 updates/20/x86_64/metalink | 15 kB 00:00 Resolving Dependencies --> Running transaction check ---> Package mysql-connector-java.noarch 1:5.1.28-1.fc20 will be installed --> Processing Dependency: jta >= 1.0 for package: 1:mysql-connector-java-5.1.28-1.fc20.noarch --> Processing Dependency: slf4j for package: 1:mysql-connector-java-5.1.28-1.fc20.noarch --> Running transaction check ---> Package geronimo-jta.noarch 0:1.1.1-15.fc20 will be installed ---> Package slf4j.noarch 0:1.7.5-3.fc20 will be installed --> Processing Dependency: mvn(log4j:log4j) for package: slf4j-1.7.5-3.fc20.noarch --> Processing Dependency: mvn(javassist:javassist) for package: slf4j-1.7.5-3.fc20.noarch --> Processing Dependency: mvn(commons-logging:commons-logging) for package: slf4j-1.7.5-3.fc20.noarch --> Processing Dependency: mvn(commons-lang:commons-lang) for package: slf4j-1.7.5-3.fc20.noarch --> Processing Dependency: mvn(ch.qos.cal10n:cal10n-api) for package: slf4j-1.7.5-3.fc20.noarch --> Running transaction check ---> Package apache-commons-lang.noarch 0:2.6-13.fc20 will be installed ---> Package apache-commons-logging.noarch 0:1.1.3-8.fc20 will be installed --> Processing Dependency: mvn(logkit:logkit) for package: apache-commons-logging-1.1.3-8.fc20.noarch --> Processing Dependency: mvn(avalon-framework:avalon-framework-api) for package: apache-commons-logging-1.1.3-8.fc20.noarch ---> Package cal10n.noarch 0:0.7.7-3.fc20 will be installed ---> Package javassist.noarch 0:3.16.1-6.fc20 will be installed ---> Package log4j.noarch 0:1.2.17-14.fc20 will be installed --> Processing Dependency: mvn(org.apache.geronimo.specs:geronimo-jms_1.1_spec) for package: log4j-1.2.17-14.fc20.noarch --> Processing Dependency: mvn(javax.mail:mail) for package: log4j-1.2.17-14.fc20.noarch --> Running transaction check ---> Package avalon-framework.noarch 0:4.3-9.fc20 will be installed --> Processing Dependency: xalan-j2 for package: avalon-framework-4.3-9.fc20.noarch ---> Package avalon-logkit.noarch 0:2.1-13.fc20 will be installed --> Processing Dependency: tomcat-servlet-3.0-api for package: avalon-logkit-2.1-13.fc20.noarch ---> Package geronimo-jms.noarch 0:1.1.1-17.fc20 will be installed ---> Package javamail.noarch 0:1.5.0-6.fc20 will be installed --> Running transaction check ---> Package tomcat-servlet-3.0-api.noarch 0:7.0.52-2.fc20 will be installed ---> Package xalan-j2.noarch 0:2.7.1-22.fc20 will be installed --> Processing Dependency: xerces-j2 for package: xalan-j2-2.7.1-22.fc20.noarch --> Processing Dependency: osgi(org.apache.xerces) for package: xalan-j2-2.7.1-22.fc20.noarch --> Running transaction check ---> Package xerces-j2.noarch 0:2.11.0-17.fc20 will be installed --> Processing Dependency: xml-commons-resolver >= 1.2 for package: xerces-j2-2.11.0-17.fc20.noarch --> Processing Dependency: xml-commons-apis >= 1.4.01 for package: xerces-j2-2.11.0-17.fc20.noarch --> Processing Dependency: osgi(org.apache.xml.resolver) for package: xerces-j2-2.11.0-17.fc20.noarch --> Processing Dependency: osgi(javax.xml) for package: xerces-j2-2.11.0-17.fc20.noarch --> Running transaction check ---> Package xml-commons-apis.noarch 0:1.4.01-14.fc20 will be installed ---> Package xml-commons-resolver.noarch 0:1.2-14.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: mysql-connector-java noarch 1:5.1.28-1.fc20 updates 1.3 M Installing for dependencies: apache-commons-lang noarch 2.6-13.fc20 fedora 281 k apache-commons-logging noarch 1.1.3-8.fc20 updates 78 k avalon-framework noarch 4.3-9.fc20 fedora 87 k avalon-logkit noarch 2.1-13.fc20 fedora 87 k cal10n noarch 0.7.7-3.fc20 fedora 37 k geronimo-jms noarch 1.1.1-17.fc20 fedora 32 k geronimo-jta noarch 1.1.1-15.fc20 fedora 21 k javamail noarch 1.5.0-6.fc20 fedora 606 k javassist noarch 3.16.1-6.fc20 fedora 626 k log4j noarch 1.2.17-14.fc20 fedora 449 k slf4j noarch 1.7.5-3.fc20 fedora 173 k tomcat-servlet-3.0-api noarch 7.0.52-2.fc20 updates 207 k xalan-j2 noarch 2.7.1-22.fc20 updates 1.9 M xerces-j2 noarch 2.11.0-17.fc20 updates 1.1 M xml-commons-apis noarch 1.4.01-14.fc20 fedora 227 k xml-commons-resolver noarch 1.2-14.fc20 fedora 108 k Transaction Summary ================================================================================ Install 1 Package (+16 Dependent packages) Total download size: 7.3 M Installed size: 10 M Downloading packages: (1/17): apache-commons-logging-1.1.3-8.fc20.noarch.rpm | 78 kB 00:00 (2/17): apache-commons-lang-2.6-13.fc20.noarch.rpm | 281 kB 00:00 (3/17): avalon-framework-4.3-9.fc20.noarch.rpm | 87 kB 00:00 (4/17): avalon-logkit-2.1-13.fc20.noarch.rpm | 87 kB 00:00 (5/17): cal10n-0.7.7-3.fc20.noarch.rpm | 37 kB 00:00 (6/17): geronimo-jms-1.1.1-17.fc20.noarch.rpm | 32 kB 00:00 (7/17): geronimo-jta-1.1.1-15.fc20.noarch.rpm | 21 kB 00:00 (8/17): javamail-1.5.0-6.fc20.noarch.rpm | 606 kB 00:00 (9/17): javassist-3.16.1-6.fc20.noarch.rpm | 626 kB 00:00 (10/17): log4j-1.2.17-14.fc20.noarch.rpm | 449 kB 00:00 (11/17): slf4j-1.7.5-3.fc20.noarch.rpm | 173 kB 00:00 (12/17): mysql-connector-java-5.1.28-1.fc20.noarch.rpm | 1.3 MB 00:01 (13/17): tomcat-servlet-3.0-api-7.0.52-2.fc20.noarch.rpm | 207 kB 00:00 (14/17): xalan-j2-2.7.1-22.fc20.noarch.rpm | 1.9 MB 00:00 (15/17): xerces-j2-2.11.0-17.fc20.noarch.rpm | 1.1 MB 00:00 (16/17): xml-commons-apis-1.4.01-14.fc20.noarch.rpm | 227 kB 00:00 (17/17): xml-commons-resolver-1.2-14.fc20.noarch.rpm | 108 kB 00:00 -------------------------------------------------------------------------------- Total 1.3 MB/s | 7.3 MB 00:05 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : xml-commons-apis-1.4.01-14.fc20.noarch 1/17 Installing : geronimo-jms-1.1.1-17.fc20.noarch 2/17 Installing : xml-commons-resolver-1.2-14.fc20.noarch 3/17 Installing : xerces-j2-2.11.0-17.fc20.noarch 4/17 Installing : xalan-j2-2.7.1-22.fc20.noarch 5/17 Installing : javamail-1.5.0-6.fc20.noarch 6/17 Installing : log4j-1.2.17-14.fc20.noarch 7/17 Installing : tomcat-servlet-3.0-api-7.0.52-2.fc20.noarch 8/17 Installing : avalon-framework-4.3-9.fc20.noarch 9/17 Installing : avalon-logkit-2.1-13.fc20.noarch 10/17 Installing : apache-commons-logging-1.1.3-8.fc20.noarch 11/17 Installing : javassist-3.16.1-6.fc20.noarch 12/17 Installing : cal10n-0.7.7-3.fc20.noarch 13/17 Installing : apache-commons-lang-2.6-13.fc20.noarch 14/17 Installing : slf4j-1.7.5-3.fc20.noarch 15/17 Installing : geronimo-jta-1.1.1-15.fc20.noarch 16/17 Installing : 1:mysql-connector-java-5.1.28-1.fc20.noarch 17/17 Verifying : geronimo-jta-1.1.1-15.fc20.noarch 1/17 Verifying : geronimo-jms-1.1.1-17.fc20.noarch 2/17 Verifying : xalan-j2-2.7.1-22.fc20.noarch 3/17 Verifying : apache-commons-lang-2.6-13.fc20.noarch 4/17 Verifying : slf4j-1.7.5-3.fc20.noarch 5/17 Verifying : log4j-1.2.17-14.fc20.noarch 6/17 Verifying : avalon-framework-4.3-9.fc20.noarch 7/17 Verifying : xerces-j2-2.11.0-17.fc20.noarch 8/17 Verifying : cal10n-0.7.7-3.fc20.noarch 9/17 Verifying : avalon-logkit-2.1-13.fc20.noarch 10/17 Verifying : 1:mysql-connector-java-5.1.28-1.fc20.noarch 11/17 Verifying : xml-commons-resolver-1.2-14.fc20.noarch 12/17 Verifying : xml-commons-apis-1.4.01-14.fc20.noarch 13/17 Verifying : javassist-3.16.1-6.fc20.noarch 14/17 Verifying : tomcat-servlet-3.0-api-7.0.52-2.fc20.noarch 15/17 Verifying : javamail-1.5.0-6.fc20.noarch 16/17 Verifying : apache-commons-logging-1.1.3-8.fc20.noarch 17/17 Installed: mysql-connector-java.noarch 1:5.1.28-1.fc20 Dependency Installed: apache-commons-lang.noarch 0:2.6-13.fc20 apache-commons-logging.noarch 0:1.1.3-8.fc20 avalon-framework.noarch 0:4.3-9.fc20 avalon-logkit.noarch 0:2.1-13.fc20 cal10n.noarch 0:0.7.7-3.fc20 geronimo-jms.noarch 0:1.1.1-17.fc20 geronimo-jta.noarch 0:1.1.1-15.fc20 javamail.noarch 0:1.5.0-6.fc20 javassist.noarch 0:3.16.1-6.fc20 log4j.noarch 0:1.2.17-14.fc20 slf4j.noarch 0:1.7.5-3.fc20 tomcat-servlet-3.0-api.noarch 0:7.0.52-2.fc20 xalan-j2.noarch 0:2.7.1-22.fc20 xerces-j2.noarch 0:2.11.0-17.fc20 xml-commons-apis.noarch 0:1.4.01-14.fc20 xml-commons-resolver.noarch 0:1.2-14.fc20 Complete! |
I must write too much Java code for the Windows platform because I didn’t notice the change in how the DriverManager
should be instantiated. Initially, I wrote the program using the following declaration for the DriverManager
class:
30 | DriverManager.registerDriver(new com.mysql.jdbc.Driver()); |
While it worked on Windows, the same syntax in the MySQL.java
program raised two errors on the Linux server. One for the declaration of the com.mysql.jdbc.Driver
class and another trying to declare an instance of Driver
class.
These are the two errors:
MySQL.java:5: error: package com.mysql.jdbc does not exist import com.mysql.jdbc.Driver; ^ MySQL.java:31: error: package com.mysql.jdbc does not exist DriverManager.registerDriver(new com.mysql.jdbc.Driver()); ^ |
I rewrote the MySQL.java
program as follows, and it works on both implementations:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 | // Import classes. import java.sql.*; /* You can't include the following on Linux without raising an exception. */ // import com.mysql.jdbc.Driver; public class MySQL { public MySQL() { /* Declare variables that require explicit assignments because they're addressed in the finally block. */ Connection conn = null; Statement stmt = null; ResultSet rset = null; /* Declare other variables. */ String url; String username = "student"; String password = "student"; String database = "studentdb"; String hostname = "localhost"; String port = "3306"; String sql; /* Attempt a connection. */ try { // Set URL. url = "jdbc:mysql://" + hostname + ":" + port + "/" + database; // Create instance of MySQL. Class.forName ("com.mysql.jdbc.Driver").newInstance(); conn = DriverManager.getConnection (url, username, password); // Query the version of the database. sql = "SELECT version()"; stmt = conn.createStatement(); rset = stmt.executeQuery(sql); System.out.println ("Database connection established"); // Read row returns for one column. while (rset.next()) { System.out.println("MySQL Version [" + rset.getString(1) + "]"); } } catch (SQLException e) { System.err.println ("Cannot connect to database server:"); System.out.println(e.getMessage()); } catch (ClassNotFoundException e) { System.err.println ("Cannot connect to database server:"); System.out.println(e.getMessage()); } catch (InstantiationException e) { System.err.println ("Cannot connect to database server:"); System.out.println(e.getMessage()); } catch (IllegalAccessException e) { System.err.println ("Cannot connect to database server:"); System.out.println(e.getMessage()); } finally { if (conn != null) { try { rset.close(); stmt.close(); conn.close(); System.out.println ("Database connection terminated"); } catch (Exception e) { /* ignore close errors */ } } } } /* Unit test. */ public static void main(String args[]) { new MySQL(); } } |
The old approach to the DriverManager
and Driver
classes disallows the use of three of the exceptions in the sample code: ClassNotFoundException
, InstantiationException
, and IllegalAccessException
classes. The new syntax works on Linux, Mac OS X, and Windows. If you’re running on Mac OS X, you need to import the following additional library in the MySQL.java
program:
import com.apple.eawt.*; |
Before you compile the MySQL.java
program, you need to put the mysql-connector-java.jar
and your present working directory into your environment’s $CLASSPATH
variable. You can set the $CLASSPATH
variable at the command-line or embed the following in your .bashrc
file:
export CLASSPATH=/usr/share/java/mysql-connector-java.jar:. |
If you embedded it in the .bashrc
file, you need to source that file or restart your terminal session, which resources the .bashrc
for you. You can source your .bashrc
file from an active Terminal session in your home directory with this syntax:
. ./.bashrc |
If you’re new to Java and the MySQL Connector/J, you compile the MySQL.java
program with the following syntax. At least, it works when you have the MySQL.java
source file in the present working directory and want to create the class file in the same directory. You can find more about the javac command-line at the www.tutorialpoint.com web site>
javac -verbose -cp . MySQL.java |
Then, you can run it with the class file with this syntax:
java MySQL |
It should return the following:
Database connection established MySQL Version [5.6.24] Database connection terminated |
If you’d prefer to return data, you can replace line 34 in the MySQL.java
program with a query against a table, like:
34 | sql = "SELECT item_title, item_rating FROM item"; |
Then, change line 42 in the MySQL.java
program with syntax to manage the output, like:
42 | System.out.println(rset.getString(1) + ", " + rset.getString(2)); } |
Recompile it, and rerun the MySQL
class file with this syntax:
java MySQL |
It should return the following:
Database connection established The Hunt for Red October, PG Star Wars I, PG Star Wars II, PG Star Wars II, PG Star Wars III, PG13 The Chronicles of Narnia, PG RoboCop, Mature Pirates of the Caribbean, Teen The Chronicles of Narnia, Everyone MarioKart, Everyone Splinter Cell, Teen Need for Speed, Everyone The DaVinci Code, Teen Cars, Everyone Beau Geste, PG I Remember Mama, NR Tora! Tora! Tora!, G A Man for All Seasons, G Hook, PG Around the World in 80 Days, G Harry Potter and the Chamber of Secrets, PG Camelot, G Database connection terminated |
As always, I hope this helps those looking for a solution.
MySQLdb Manage Columns
Sometimes trying to keep a post short and to the point raises other questions. Clearly, my Python-MySQL Program post over the weekend did raise a question. They were extending the query example and encountered this error:
TypeError: range() integer end argument expected, got tuple. |
That should be a straight forward error message because of two things. First, the Python built-in range()
function manages a range of numbers. Second, the row returned from a cursor is actually a tuple (from relational algebra), and it may contain non-numeric data like strings and dates.
The reader was trying to dynamically navigate the number of columns in a row by using the range()
function like this (where row was a row from the cursor or result set):
for j in range(row): |
Naturally, it threw the type mismatch error noted above. As promised, the following Python program fixes that problem. It also builds on the prior example by navigatung an unknown list of columns. Lines 16 through 31 contain the verbose comments and programming logic to dynamically navigate the columns of a row.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | #!/usr/bin/python # Import sys library. import MySQLdb import sys try: # Create new database connection. db = MySQLdb.connect('localhost','student','student','studentdb') # Create a result set cursor. rs = db.cursor() rs.execute("SELECT item_title, item_subtitle, item_rating FROM item") # Assign the query results to a local variable. for i in range(rs.rowcount): row = rs.fetchone() # Initialize variable for printing row as a string. data = "" # Address an indefinite number of columns. count = 0 for j in range(len(row)): # Initialize column value as an empty string. datum = "" # Replace column values when they exist. if str(row[count]) != 'None': datum = str(row[count]) # Append a comma when another column follows. if count == len(row) - 1: data += datum else: data += datum + ", " count += 1 # Print the formatted row as a string. print data except MySQLdb.Error, e: # Print the error. print "ERROR %d: %s" % (e.args[0], e.args[1]) sys.exit(1) finally: # Close the connection when it is open. if db: db.close() |
There are a couple Python programming techniques that could be perceived as tricks. Line 24 checks for a not null value by explicitly casting the column’s value to a string and then comparing its value against the string equivalent for a null. The MySQLdb returns a 'None'
string for null values by default. The if
-block on lines 27 through 30 ensure commas aren’t appended at the end of a row.
While the for
-loop with a range works, I’d recommend you write it as a while
-loop because its easier to read for most new Python programmers. You only need to replace line 20 with the following to make the change:
20 | while (count < len(row)): |
Either approach generates output like:
The Hunt for Red October, Special Collectornulls Edition, PG Star Wars I, Phantom Menace, PG Star Wars II, Attack of the Clones, PG Star Wars II, Attack of the Clones, PG Star Wars III, Revenge of the Sith, PG-13 The Chronicles of Narnia, The Lion, the Witch and the Wardrobe, PG RoboCop, , Mature Pirates of the Caribbean, , Teen The Chronicles of Narnia, The Lion, the Witch and the Wardrobe, Everyone MarioKart, Double Dash, Everyone Splinter Cell, Chaos Theory, Teen Need for Speed, Most Wanted, Everyone The DaVinci Code, , Teen Cars, , Everyone Beau Geste, , PG I Remember Mama, , NR Tora! Tora! Tora!, The Attack on Pearl Harbor, G A Man for All Seasons, , G Hook, , PG Around the World in 80 Days, , G Harry Potter and the Sorcerer's Stone, , PG Camelot, , G |
As always, I hope this helps those looking for clarity.
Perl-MySQL Program
Configuring Perl to work with MySQL is the last part creating a complete Fedora Linux LAMP stack for my students. Perl is already installed on Fedora Linux.
I’ve also shown how to use PHP, Python, and Ruby languages to query a MySQL database on Linux. After installing this additional Perl DBI library, my students will have the opportunity to choose how they implement their LAMP solution.
You can find the Perl version with the following version.pl
program:
1 2 3 4 | #!/usr/bin/perl -w # Print the version. print "Perl ".$]."\n"; |
The first line lets you call the program without prefacing the perl
program because it invokes a subshell of perl
by default. You just need to ensure the file has read and execute privileges to run. It prints:
Perl 5.018004 |
You need to install the perl-DBD-MySQL
library to enable Perl to work with MySQL. The following command loads the library:
yum install -y perl-DBD-MySQL |
It prints the following log file:
Loaded plugins: langpacks, refresh-packagekit Resolving Dependencies --> Running transaction check ---> Package perl-DBD-MySQL.x86_64 0:4.024-1.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: perl-DBD-MySQL x86_64 4.024-1.fc20 fedora 142 k Transaction Summary ================================================================================ Install 1 Package Total download size: 142 k Installed size: 332 k Downloading packages: perl-DBD-MySQL-4.024-1.fc20.x86_64.rpm | 142 kB 00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : perl-DBD-MySQL-4.024-1.fc20.x86_64 1/1 Verifying : perl-DBD-MySQL-4.024-1.fc20.x86_64 1/1 Installed: perl-DBD-MySQL.x86_64 0:4.024-1.fc20 Complete! |
The following item_query.pl
Perl program is consistent with the PHP, Python, and Ruby examples provided in other blog posts. It shows you how to use the Perl DBI library to query and return a data set.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/usr/bin/perl -w # Use the DBI library. use DBI; use strict; use warnings; # Create a connection. my $dbh = DBI->connect("DBI:mysql:database=studentdb;host=localhost:3306","student","student",{'RaiseError' => 1}); # Create SQL statement. my $sql = "SELECT item_title FROM item"; # Prepare SQL statement. my $sth = $dbh->prepare($sql); # Execute statement and read result set. $sth->execute() or die $DBI::errstr; while (my @row = $sth->fetchrow_array()) { my $item_title = $row[0]; print "$item_title\n"; } # Close resources. $sth->finish(); |
You call it like this from the present working directory:
./mysql_query.pl |
It returns:
The Hunt for Red October Star Wars I Star Wars II Star Wars II Star Wars III The Chronicles of Narnia RoboCop Pirates of the Caribbean The Chronicles of Narnia MarioKart Splinter Cell Need for Speed The DaVinci Code Cars Beau Geste I Remember Mama Tora! Tora! Tora! A Man for All Seasons Hook Around the World in 80 Days Harry Potter and the Sorcerer's Stone Camelot |
Alternatively, there’s a different syntax for lines 20 and 21 that you can use when you’re returning multiple columns. It replaces the two statements inside the while loop as follows:
20 21 | my ($item_title, $item_rating) = @row; print "$item_title, $item_rating\n"; |
It returns:
The Hunt for Red October, PG Star Wars I, PG Star Wars II, PG Star Wars II, PG Star Wars III, PG13 The Chronicles of Narnia, PG RoboCop, Mature Pirates of the Caribbean, Teen The Chronicles of Narnia, Everyone MarioKart, Everyone Splinter Cell, Teen Need for Speed, Everyone The DaVinci Code, Teen Cars, Everyone Beau Geste, PG I Remember Mama, NR Tora! Tora! Tora!, G A Man for All Seasons, G Hook, PG Around the World in 80 Days, G Harry Potter and the Sorcerer's Stone, PG Camelot, G |
As always, I hope this helps those learning how to use Perl and Linux against the MySQL Database. If you want a nice tutorial on Perl and MySQL, check The tutorialspoint.com web site.
Python-MySQL Program
This post works through the Python configuration of Fedora instance, and continues the configuration of my LAMP VMware instance. It covers how you add the MySQL-python
libraries to the Fedora instance, and provides the students with one more language opportunity for their capstone lab in the database class.
A standard Fedora Linux distribution installs Python 2.7 by default. Unfortunately, the MySQL-python
library isn’t installed by default. You can verify the Python version by writing and running the following version.py
program before installing the MySQL-python
library:
1 2 3 4 5 | # Import sys library. import sys # Print the Python version. print sys.version |
You can run the version.py
program dynamically like this from the current working directory:
python version.py |
It will print the following:
2.7.5 (default, Nov 3 2014, 14:26:24) [GCC 4.8.3 20140911 (Red Hat 4.8.3-7)] |
If you modify the program by adding the following first line
1 2 3 4 5 6 7 | #!/usr/bin/python # Import sys library. import sys # Print the Python version. print sys.version |
Provided you’ve set the file permissions to read and execute, you can run the program by simply calling version.py
like this from the present working directory:
./version.py |
You can install the MySQL-python
library with the yum
utility like this:
yum install -y MySQL-python |
It shows you the following output:
Loaded plugins: langpacks, refresh-packagekit mysql-connectors-community | 2.5 kB 00:00 mysql-tools-community | 2.5 kB 00:00 mysql56-community | 2.5 kB 00:00 pgdg93 | 3.6 kB 00:00 updates/20/x86_64/metalink | 12 kB 00:00 updates | 4.9 kB 00:00 updates/20/x86_64/primary_db | 13 MB 00:04 (1/2): updates/20/x86_64/updateinfo | 1.9 MB 00:02 (2/2): updates/20/x86_64/pkgtags | 1.4 MB 00:02 Resolving Dependencies --> Running transaction check ---> Package MySQL-python.x86_64 0:1.2.3-8.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: MySQL-python x86_64 1.2.3-8.fc20 fedora 82 k Transaction Summary ================================================================================ Install 1 Package Total download size: 82 k Installed size: 231 k Downloading packages: MySQL-python-1.2.3-8.fc20.x86_64.rpm | 82 kB 00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : MySQL-python-1.2.3-8.fc20.x86_64 1/1 Verifying : MySQL-python-1.2.3-8.fc20.x86_64 1/1 Installed: MySQL-python.x86_64 0:1.2.3-8.fc20 Complete! |
After installing the MySQL-python
library, you can call the following mysql_connect.py
program from the local directory:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | #!/usr/bin/python # Import sys library. import MySQLdb import sys try: # Create new database connection. db = MySQLdb.connect('localhost','student','student','studentdb') # Query the version of the MySQL database. db.query("SELECT version()") # Assign the query results to a local variable. result = db.use_result() # Print the results. print "MySQL Version: %s " % result.fetch_row()[0] except MySQLdb.Error, e: # Print the error. print "ERROR %d: %s" % (e.args[0], e.args[1]) sys.exit(1) finally: # Close the connection when it is open. if db: db.close() |
Like the version.py
program, set the file permissions to read and execute and call , you can run the program by simply calling mysql_connect.py
program like this from the present working directory:
./mysql_connect.py |
The mysql_connect.py
program displays:
MySQL Version: 5.6.24 |
After verifying the MySQL connection, you can query actual data with the following mysql_queryset.py
program:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | #!/usr/bin/python # Import sys library. import MySQLdb import sys try: # Create new database connection. db = MySQLdb.connect('localhost','student','student','studentdb') # Create a result set cursor. rs = db.cursor() rs.execute("SELECT item_title FROM item") # Assign the query results to a local variable. rows = rs.fetchall() # Print the results. for row in rows: print row except MySQLdb.Error, e: # Print the error. print "ERROR %d: %s" % (e.args[0], e.args[1]) sys.exit(1) finally: # Close the connection when it is open. if db: db.close() |
You call the mysql_queryset.py
file from the present working directory like this:
./mysql_queryset.py |
It prints the following:
('The Hunt for Red October',) ('Star Wars I',) ('Star Wars II',) ('Star Wars II',) ('Star Wars III',) ('The Chronicles of Narnia',) ('RoboCop',) ('Pirates of the Caribbean',) ('The Chronicles of Narnia',) ('MarioKart',) ('Splinter Cell',) ('Need for Speed',) ('The DaVinci Code',) ('Cars',) ('Beau Geste',) ('I Remember Mama',) ('Tora! Tora! Tora!',) ('A Man for All Seasons',) ('Hook',) ('Around the World in 80 Days',) ("Harry Potter and the Sorcerer's Stone",) ('Camelot',) |
You can substantially improve on the behavior of the prior example by handling each row one at a time. The following mysql_query.py
program reads through the cursor result set one row at a time:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | #!/usr/bin/python # Import sys library. import MySQLdb import sys try: # Create new database connection. db = MySQLdb.connect('localhost','student','student','studentdb') # Create a result set cursor. rs = db.cursor() rs.execute("SELECT item_title FROM item") # Assign the query results to a local variable. for i in range(rs.rowcount): row = rs.fetchone() print row[0] except MySQLdb.Error, e: # Print the error. print "ERROR %d: %s" % (e.args[0], e.args[1]) sys.exit(1) finally: # Close the connection when it is open. if db: db.close() |
You call the mysql_query.py
with the following syntax:
./mysql_query.py |
It returns the following result set:
The Hunt for Red October Star Wars I Star Wars II Star Wars II Star Wars III The Chronicles of Narnia RoboCop Pirates of the Caribbean The Chronicles of Narnia MarioKart Splinter Cell Need for Speed The DaVinci Code Cars Beau Geste I Remember Mama Tora! Tora! Tora! A Man for All Seasons Hook Around the World in 80 Days Harry Potter and the Sorcerer's Stone Camelot |
As always, I hope this helps those looking for this type of solution. The Python tutorial web site teaches you more about the Python Programming Language. You may also find the TutorialsPoint.com site useful while you’re learning and using Python. The MySQLdb User’s Guide teaches more about working writing Python-MySQL library. The MySQLdb implements the Python Database API Specification v2.0.
MySQL JSON Functions
What the MySQL team is doing with JSON (JavaScript Object Notation) in MySQL 5.7 is great! The MySQL Server Blog (Rick Hillegas and Dag Wanvik) published two key articles about new JSON functions. If you don’t follow these, let me highlight them as a set:
Most folks know how important JSON is to web development. I like the following visual that highlights it. It was provided as a comment to this earlier Popular Programming Language post by Michael Farmer. Clearly, JavaScript is popular because it’s critical to effective web development. If you’re new to JSON, check out Adam Khoury’s JSON tutorial set on YouTube.
If you want the original graphic, you can find it here. It’s always to hard to keep up with the technology, isn’t it? 🙂
Ruby-MySQL Program
After you install Ruby and build the Rails framework, you need to create the mysql
gem. This blog post shows you how to create the mysql
gem and how to write a simple Ruby program that queries the MySQL database.
The first step creates the mysql
gem for Ruby programming:
gem install mysql |
It should show you the following:
Fetching: mysql-2.9.1.gem (100%) Building native extensions. This could take a while... Successfully installed mysql-2.9.1 Parsing documentation for mysql-2.9.1 Installing ri documentation for mysql-2.9.1 Done installing documentation for mysql after 0 seconds 1 gem installed |
After you install the mysql
Ruby Gem, you can write and test a test.rb
Ruby program that tests a MySQL database connection. The simplest complete code looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | # Include Ruby Gem libraries. require 'rubygems' require 'mysql' begin # Create new database connection. db = Mysql.new('localhost','student','student','studentdb') # Print connected message. puts "Connected to the MySQL database server." rescue Mysql::Error => e # Print the error. puts "ERROR #{e.errno} (#{e.sqlstate}): #{e.error}" puts "Can't connect to the MySQL database specified." # Signal an error. exit 1 ensure # Close the connection when it is open. db.close if db end |
You can run the program with the following syntax:
ruby test.rb |
The program prints “Connected to the MySQL database server.” when there’s a student
user with a student
password that’s authorized to connect to the studentdb
database. If any of the values are invalid when creating the connection, the program prints “Can’t connect to the MySQL database specified.”
Having tested the connection, the next query.rb
program tests the connection by returning values from a query:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | # Include Ruby Gem libraries. require 'rubygems' require 'mysql' # Begin block. begin # Create a new connection resource. db = Mysql.new('localhost','student','student','studentdb1') # Create a result set. rs = db.query('SELECT item_title FROM item') # Read through the result set hash. rs.each_hash do | row | puts "#{row['item_title']}" end # Release the result set resources. rs.free rescue Mysql::Error => e # Print the error. puts "ERROR #{e.errno} (#{e.sqlstate}): #{e.error}" puts "Can't connect to MySQL database specified." # Signal an error. exit 1 ensure # Close the connection when it is open. db.close if db end |
You can test it with the following command-line syntax:
ruby query.rb |
It returns a data set like this from the item
table of my video store example:
+---------------------------------------+ | item_title | +---------------------------------------+ | The Hunt for Red October | | Star Wars I | | Star Wars II | | Star Wars II | | Star Wars III | | The Chronicles of Narnia | | RoboCop | | Pirates of the Caribbean | | The Chronicles of Narnia | | MarioKart | | Splinter Cell | | Need for Speed | | The DaVinci Code | | Cars | | Beau Geste | | I Remember Mama | | Tora! Tora! Tora! | | A Man for All Seasons | | Hook | | Around the World in 80 Days | | Harry Potter and the Sorcerer's Stone | | Camelot | +---------------------------------------+ 22 rows in set (0.00 sec) |
You need the ruby
interpreter to run them. You can make the programs standalone operations by putting the following line as the first line in your Ruby programs.
1 | #!/usr/bin/ruby |
Then, you can run the program like this if they have read and execute privileges and are located in the present working directory where you issue the following command:
./mysql_query.rb |
If you want to work with individual columns, please check this subsequent post that shows how you can access individual columns. As always, I hope this helps those trying to get things working.
After posting this somebody asked for books that could help them learn how to write Ruby programs. While books are nice and listed below, I’d start with the tryruby.org web site.
I’d recommend the following books because …
- The Ruby Programming Language is 7 years old now and only covers Ruby 1.8 and 1.9, but its written by David Flanagan and the creator of the Ruby Programming Language – Yukihiro Matsumoto.
- Programming Ruby 1.9 & 2.0: The Pragmatic Programmer’s Guide is more current and a well balanced approach at learning how to write Ruby programs.
- The Well-Grounded Rubyist is the most current book and teaches you how to think about writing Ruby beyond just the syntax. As a Manning book, you can purchase the physical copy and automatically get a downloadable ebook. It’s certainly the best value for the money option provided you already know how to program in at least one other object-oriented programming language.
Install Ruby on Fedora
I use a Fedora 20 VM image to teach Oracle and MySQL technology. Last week, I expanded the Fedora VM image to support a full LAMP stack. This blog shows you how to install Ruby on Fedora and successfully generate the Rails gems.
Connect as the root
user and use yum to install the libraries. My approach is by library or small groups. Naturally, you start with the ruby
library.
yum install ruby |
You will see the following:
Loaded plugins: langpacks, refresh-packagekit mysql-connectors-community | 2.5 kB 00:00 mysql-tools-community | 2.5 kB 00:00 mysql56-community | 2.5 kB 00:00 pgdg93 | 3.6 kB 00:00 updates/20/x86_64/metalink | 14 kB 00:00 updates | 4.9 kB 00:00 (1/3): mysql56-community/20/x86_64/primary_db | 80 kB 00:00 (2/3): pgdg93/20/x86_64/primary_db | 80 kB 00:00 (3/3): updates/20/x86_64/primary_db | 13 MB 00:06 (1/2): updates/20/x86_64/pkgtags | 1.4 MB 00:01 (2/2): updates/20/x86_64/updateinfo | 1.9 MB 00:01 Resolving Dependencies --> Running transaction check ---> Package ruby.x86_64 0:2.0.0.353-16.fc20 will be installed --> Processing Dependency: ruby-libs(x86-64) = 2.0.0.353-16.fc20 for package: ruby-2.0.0.353-16.fc20.x86_64 --> Processing Dependency: rubygem(bigdecimal) >= 1.2.0 for package: ruby-2.0.0.353-16.fc20.x86_64 --> Processing Dependency: ruby(rubygems) >= 2.0.3 for package: ruby-2.0.0.353-16.fc20.x86_64 --> Processing Dependency: /usr/bin/ruby for package: ruby-2.0.0.353-16.fc20.x86_64 --> Processing Dependency: libruby.so.2.0()(64bit) for package: ruby-2.0.0.353-16.fc20.x86_64 --> Running transaction check ---> Package ruby-libs.x86_64 0:2.0.0.353-16.fc20 will be installed ---> Package rubygem-bigdecimal.x86_64 0:1.2.0-16.fc20 will be installed ---> Package rubygems.noarch 0:2.1.11-115.fc20 will be installed --> Processing Dependency: rubygem(rdoc) >= 4.0.0 for package: rubygems-2.1.11-115.fc20.noarch --> Processing Dependency: rubygem(psych) >= 2.0.0 for package: rubygems-2.1.11-115.fc20.noarch --> Processing Dependency: rubygem(io-console) >= 0.4.1 for package: rubygems-2.1.11-115.fc20.noarch ---> Package rubypick.noarch 0:1.1.1-1.fc20 will be installed --> Running transaction check ---> Package rubygem-io-console.x86_64 0:0.4.2-16.fc20 will be installed ---> Package rubygem-psych.x86_64 0:2.0.0-16.fc20 will be installed --> Processing Dependency: libyaml-0.so.2()(64bit) for package: rubygem-psych-2.0.0-16.fc20.x86_64 ---> Package rubygem-rdoc.noarch 0:4.0.1-2.fc20 will be installed --> Processing Dependency: rubygem(json) < 2 for package: rubygem-rdoc-4.0.1-2.fc20.noarch --> Processing Dependency: rubygem(json) >= 1.4 for package: rubygem-rdoc-4.0.1-2.fc20.noarch --> Processing Dependency: ruby(irb) for package: rubygem-rdoc-4.0.1-2.fc20.noarch --> Running transaction check ---> Package libyaml.x86_64 0:0.1.6-2.fc20 will be installed ---> Package ruby-irb.noarch 0:2.0.0.353-16.fc20 will be installed ---> Package rubygem-json.x86_64 0:1.7.7-101.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: ruby x86_64 2.0.0.353-16.fc20 updates 65 k Installing for dependencies: libyaml x86_64 0.1.6-2.fc20 updates 55 k ruby-irb noarch 2.0.0.353-16.fc20 updates 86 k ruby-libs x86_64 2.0.0.353-16.fc20 updates 2.8 M rubygem-bigdecimal x86_64 1.2.0-16.fc20 updates 77 k rubygem-io-console x86_64 0.4.2-16.fc20 updates 48 k rubygem-json x86_64 1.7.7-101.fc20 fedora 60 k rubygem-psych x86_64 2.0.0-16.fc20 updates 75 k rubygem-rdoc noarch 4.0.1-2.fc20 fedora 288 k rubygems noarch 2.1.11-115.fc20 updates 224 k rubypick noarch 1.1.1-1.fc20 updates 6.3 k Transaction Summary ================================================================================ Install 1 Package (+10 Dependent packages) Total download size: 3.7 M Installed size: 13 M Is this ok [y/d/N]: y Downloading packages: (1/11): ruby-2.0.0.353-16.fc20.x86_64.rpm | 65 kB 00:00 (2/11): libyaml-0.1.6-2.fc20.x86_64.rpm | 55 kB 00:00 (3/11): ruby-irb-2.0.0.353-16.fc20.noarch.rpm | 86 kB 00:00 (4/11): rubygem-io-console-0.4.2-16.fc20.x86_64.rpm | 48 kB 00:00 (5/11): rubygem-json-1.7.7-101.fc20.x86_64.rpm | 60 kB 00:00 (6/11): rubygem-psych-2.0.0-16.fc20.x86_64.rpm | 75 kB 00:00 (7/11): rubypick-1.1.1-1.fc20.noarch.rpm | 6.3 kB 00:00 (8/11): rubygem-bigdecimal-1.2.0-16.fc20.x86_64.rpm | 77 kB 00:01 (9/11): rubygem-rdoc-4.0.1-2.fc20.noarch.rpm | 288 kB 00:00 (10/11): ruby-libs-2.0.0.353-16.fc20.x86_64.rpm | 2.8 MB 00:01 (11/11): rubygems-2.1.11-115.fc20.noarch.rpm | 224 kB 00:01 -------------------------------------------------------------------------------- Total 1.4 MB/s | 3.7 MB 00:02 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : ruby-libs-2.0.0.353-16.fc20.x86_64 1/11 Installing : libyaml-0.1.6-2.fc20.x86_64 2/11 Installing : rubygem-bigdecimal-1.2.0-16.fc20.x86_64 3/11 Installing : rubygem-json-1.7.7-101.fc20.x86_64 4/11 Installing : rubygem-psych-2.0.0-16.fc20.x86_64 5/11 Installing : rubygem-rdoc-4.0.1-2.fc20.noarch 6/11 Installing : ruby-irb-2.0.0.353-16.fc20.noarch 7/11 Installing : rubypick-1.1.1-1.fc20.noarch 8/11 Installing : ruby-2.0.0.353-16.fc20.x86_64 9/11 Installing : rubygems-2.1.11-115.fc20.noarch 10/11 Installing : rubygem-io-console-0.4.2-16.fc20.x86_64 11/11 Verifying : rubygem-io-console-0.4.2-16.fc20.x86_64 1/11 Verifying : rubygem-rdoc-4.0.1-2.fc20.noarch 2/11 Verifying : rubygems-2.1.11-115.fc20.noarch 3/11 Verifying : rubygem-bigdecimal-1.2.0-16.fc20.x86_64 4/11 Verifying : ruby-libs-2.0.0.353-16.fc20.x86_64 5/11 Verifying : rubygem-json-1.7.7-101.fc20.x86_64 6/11 Verifying : rubygem-psych-2.0.0-16.fc20.x86_64 7/11 Verifying : rubypick-1.1.1-1.fc20.noarch 8/11 Verifying : ruby-2.0.0.353-16.fc20.x86_64 9/11 Verifying : libyaml-0.1.6-2.fc20.x86_64 10/11 Verifying : ruby-irb-2.0.0.353-16.fc20.noarch 11/11 Installed: ruby.x86_64 0:2.0.0.353-16.fc20 Dependency Installed: libyaml.x86_64 0:0.1.6-2.fc20 ruby-irb.noarch 0:2.0.0.353-16.fc20 ruby-libs.x86_64 0:2.0.0.353-16.fc20 rubygem-bigdecimal.x86_64 0:1.2.0-16.fc20 rubygem-io-console.x86_64 0:0.4.2-16.fc20 rubygem-json.x86_64 0:1.7.7-101.fc20 rubygem-psych.x86_64 0:2.0.0-16.fc20 rubygem-rdoc.noarch 0:4.0.1-2.fc20 rubygems.noarch 0:2.1.11-115.fc20 rubypick.noarch 0:1.1.1-1.fc20 Complete! |
After you install ruby
, you need to install the MySQL and Ruby development libraries, like this:
yum -y install gcc mysql-devel ruby-devel rubygems |
Loaded plugins: langpacks, refresh-packagekit Package gcc-4.8.3-7.fc20.x86_64 already installed and latest version Package rubygems-2.1.11-115.fc20.noarch already installed and latest version Resolving Dependencies --> Running transaction check ---> Package mysql-community-devel.x86_64 0:5.6.24-1.fc20 will be installed --> Processing Dependency: mysql-community-libs(x86-64) = 5.6.24-1.fc20 for package: mysql-community-devel-5.6.24-1.fc20.x86_64 ---> Package ruby-devel.x86_64 0:2.0.0.353-16.fc20 will be installed --> Running transaction check ---> Package mysql-community-libs.x86_64 0:5.6.23-1.fc20 will be updated --> Processing Dependency: mysql-community-libs(x86-64) = 5.6.23-1.fc20 for package: mysql-community-client-5.6.23-1.fc20.x86_64 ---> Package mysql-community-libs.x86_64 0:5.6.24-1.fc20 will be an update --> Processing Dependency: mysql-community-common(x86-64) = 5.6.24-1.fc20 for package: mysql-community-libs-5.6.24-1.fc20.x86_64 --> Running transaction check ---> Package mysql-community-client.x86_64 0:5.6.23-1.fc20 will be updated --> Processing Dependency: mysql-community-client(x86-64) = 5.6.23-1.fc20 for package: mysql-community-server-5.6.23-1.fc20.x86_64 ---> Package mysql-community-client.x86_64 0:5.6.24-1.fc20 will be an update ---> Package mysql-community-common.x86_64 0:5.6.23-1.fc20 will be updated ---> Package mysql-community-common.x86_64 0:5.6.24-1.fc20 will be an update --> Running transaction check ---> Package mysql-community-server.x86_64 0:5.6.23-1.fc20 will be updated ---> Package mysql-community-server.x86_64 0:5.6.24-1.fc20 will be an update --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: mysql-community-devel x86_64 5.6.24-1.fc20 mysql56-community 3.4 M ruby-devel x86_64 2.0.0.353-16.fc20 updates 125 k Updating for dependencies: mysql-community-client x86_64 5.6.24-1.fc20 mysql56-community 19 M mysql-community-common x86_64 5.6.24-1.fc20 mysql56-community 258 k mysql-community-libs x86_64 5.6.24-1.fc20 mysql56-community 2.0 M mysql-community-server x86_64 5.6.24-1.fc20 mysql56-community 55 M Transaction Summary ================================================================================ Install 2 Packages Upgrade ( 4 Dependent packages) Total download size: 80 M Downloading packages: No Presto metadata available for mysql56-community (1/6): mysql-community-common-5.6.24-1.fc20.x86_64.rpm | 258 kB 00:01 (2/6): mysql-community-devel-5.6.24-1.fc20.x86_64.rpm | 3.4 MB 00:01 (3/6): mysql-community-libs-5.6.24-1.fc20.x86_64.rpm | 2.0 MB 00:00 (4/6): ruby-devel-2.0.0.353-16.fc20.x86_64.rpm | 125 kB 00:00 (5/6): mysql-community-client-5.6.24-1.fc20.x86_64.rpm | 19 MB 00:09 (6/6): mysql-community-server-5.6.24-1.fc20.x86_64.rpm | 55 MB 00:21 -------------------------------------------------------------------------------- Total 3.3 MB/s | 80 MB 00:24 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Updating : mysql-community-common-5.6.24-1.fc20.x86_64 1/10 Updating : mysql-community-libs-5.6.24-1.fc20.x86_64 2/10 Updating : mysql-community-client-5.6.24-1.fc20.x86_64 3/10 Updating : mysql-community-server-5.6.24-1.fc20.x86_64 4/10 Installing : mysql-community-devel-5.6.24-1.fc20.x86_64 5/10 Installing : ruby-devel-2.0.0.353-16.fc20.x86_64 6/10 Cleanup : mysql-community-server-5.6.23-1.fc20.x86_64 7/10 Cleanup : mysql-community-client-5.6.23-1.fc20.x86_64 8/10 Cleanup : mysql-community-libs-5.6.23-1.fc20.x86_64 9/10 Cleanup : mysql-community-common-5.6.23-1.fc20.x86_64 10/10 Verifying : mysql-community-client-5.6.24-1.fc20.x86_64 1/10 Verifying : mysql-community-devel-5.6.24-1.fc20.x86_64 2/10 Verifying : ruby-devel-2.0.0.353-16.fc20.x86_64 3/10 Verifying : mysql-community-libs-5.6.24-1.fc20.x86_64 4/10 Verifying : mysql-community-common-5.6.24-1.fc20.x86_64 5/10 Verifying : mysql-community-server-5.6.24-1.fc20.x86_64 6/10 Verifying : mysql-community-client-5.6.23-1.fc20.x86_64 7/10 Verifying : mysql-community-server-5.6.23-1.fc20.x86_64 8/10 Verifying : mysql-community-libs-5.6.23-1.fc20.x86_64 9/10 Verifying : mysql-community-common-5.6.23-1.fc20.x86_64 10/10 Installed: mysql-community-devel.x86_64 0:5.6.24-1.fc20 ruby-devel.x86_64 0:2.0.0.353-16.fc20 Dependency Updated: mysql-community-client.x86_64 0:5.6.24-1.fc20 mysql-community-common.x86_64 0:5.6.24-1.fc20 mysql-community-libs.x86_64 0:5.6.24-1.fc20 mysql-community-server.x86_64 0:5.6.24-1.fc20 Complete! |
After installing ruby, exit the root account to your management account and run the following command from the Linux shell:
ruby -v |
It should show you:
ruby 2.0.0p353 (2013-11-22 revision 43784) [x86_64-linux] |
Before you can run gem
to install rails
, you must install another the libxml2-devel
library. Here’s the syntax to install the libxml2-devel
library:
yum install libxml2-devel |
You should see the following, which includes typing a y
to continue:
Loaded plugins: langpacks, refresh-packagekit Resolving Dependencies --> Running transaction check ---> Package libxml2-devel.x86_64 0:2.9.1-3.fc20 will be installed --> Processing Dependency: zlib-devel for package: libxml2-devel-2.9.1-3.fc20.x86_64 --> Processing Dependency: xz-devel for package: libxml2-devel-2.9.1-3.fc20.x86_64 --> Running transaction check ---> Package xz-devel.x86_64 0:5.1.2-12alpha.fc20 will be installed ---> Package zlib-devel.x86_64 0:1.2.8-3.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: libxml2-devel x86_64 2.9.1-3.fc20 updates 1.0 M Installing for dependencies: xz-devel x86_64 5.1.2-12alpha.fc20 updates 45 k zlib-devel x86_64 1.2.8-3.fc20 fedora 50 k Transaction Summary ================================================================================ Install 1 Package (+2 Dependent packages) Total download size: 1.1 M Installed size: 9.1 M Is this ok [y/d/N]: y Downloading packages: (1/3): xz-devel-5.1.2-12alpha.fc20.x86_64.rpm | 45 kB 00:00 (2/3): zlib-devel-1.2.8-3.fc20.x86_64.rpm | 50 kB 00:00 (3/3): libxml2-devel-2.9.1-3.fc20.x86_64.rpm | 1.0 MB 00:04 -------------------------------------------------------------------------------- Total 264 kB/s | 1.1 MB 00:04 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : zlib-devel-1.2.8-3.fc20.x86_64 1/3 Installing : xz-devel-5.1.2-12alpha.fc20.x86_64 2/3 Installing : libxml2-devel-2.9.1-3.fc20.x86_64 3/3 Verifying : xz-devel-5.1.2-12alpha.fc20.x86_64 1/3 Verifying : libxml2-devel-2.9.1-3.fc20.x86_64 2/3 Verifying : zlib-devel-1.2.8-3.fc20.x86_64 3/3 Installed: libxml2-devel.x86_64 0:2.9.1-3.fc20 Dependency Installed: xz-devel.x86_64 0:5.1.2-12alpha.fc20 zlib-devel.x86_64 0:1.2.8-3.fc20 Complete! |
yum install libxslt-devel |
You should see the following and will need to reply with a y during install:
Loaded plugins: langpacks, refresh-packagekit mysql-connectors-community | 2.5 kB 00:00 mysql-tools-community | 2.5 kB 00:00 mysql56-community | 2.5 kB 00:00 pgdg93 | 3.6 kB 00:00 updates/20/x86_64/metalink | 14 kB 00:00 updates | 4.9 kB 00:00 updates/20/x86_64/primary_db | 13 MB 00:07 updates/20/x86_64/pkgtags FAILED http://mirror.utexas.edu/fedora/linux/updates/20/x86_64/repodata/fe40e35e0289ae1470dbe8030c09b8046924cbaa5e16ac61e9411ac57477820b-pkgtags.sqlite.gz: [Errno 14] HTTP Error 404 - Not Found Trying other mirror. (1/2): updates/20/x86_64/updateinfo | 1.9 MB 00:02 (2/2): updates/20/x86_64/pkgtags | 1.4 MB 00:00 Resolving Dependencies --> Running transaction check ---> Package libxslt-devel.x86_64 0:1.1.28-5.fc20 will be installed --> Processing Dependency: libgcrypt-devel for package: libxslt-devel-1.1.28-5.fc20.x86_64 --> Running transaction check ---> Package libgcrypt-devel.x86_64 0:1.5.3-2.fc20 will be installed --> Processing Dependency: libgpg-error-devel for package: libgcrypt-devel-1.5.3-2.fc20.x86_64 --> Running transaction check ---> Package libgpg-error-devel.x86_64 0:1.12-1.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: libxslt-devel x86_64 1.1.28-5.fc20 fedora 309 k Installing for dependencies: libgcrypt-devel x86_64 1.5.3-2.fc20 fedora 127 k libgpg-error-devel x86_64 1.12-1.fc20 fedora 16 k Transaction Summary ================================================================================ Install 1 Package (+2 Dependent packages) Total download size: 451 k Installed size: 2.6 M Is this ok [y/d/N]: y Downloading packages: (1/3): libgcrypt-devel-1.5.3-2.fc20.x86_64.rpm | 127 kB 00:00 (2/3): libgpg-error-devel-1.12-1.fc20.x86_64.rpm | 16 kB 00:00 (3/3): libxslt-devel-1.1.28-5.fc20.x86_64.rpm | 309 kB 00:00 -------------------------------------------------------------------------------- Total 454 kB/s | 451 kB 00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : libgpg-error-devel-1.12-1.fc20.x86_64 1/3 Installing : libgcrypt-devel-1.5.3-2.fc20.x86_64 2/3 Installing : libxslt-devel-1.1.28-5.fc20.x86_64 3/3 Verifying : libgcrypt-devel-1.5.3-2.fc20.x86_64 1/3 Verifying : libgpg-error-devel-1.12-1.fc20.x86_64 2/3 Verifying : libxslt-devel-1.1.28-5.fc20.x86_64 3/3 Installed: libxslt-devel.x86_64 0:1.1.28-5.fc20 Dependency Installed: libgcrypt-devel.x86_64 0:1.5.3-2.fc20 libgpg-error-devel.x86_64 0:1.12-1.fc20 Complete! |
One more to go. You can’t run the Ruby gem
utility to create the nokogiri
Ruby Gem on Fedora because of a library mismatch. If you attempt to create the Rails framework, like this:
gem install rails |
It’ll raise the following error message on trying to dynamically link the nokogiri
Ruby Gem. The error will be something like this, and unfortunately, the log files won’t be too useful:
Running patch with /usr/local/share/gems/gems/nokogiri-1.6.6.2/ports/patches/libxml2/0001-Revert-Missing-initialization-for-the-catalog-module.patch... Running 'patch' for libxml2 2.9.2... ERROR, review '/usr/local/share/gems/gems/nokogiri-1.6.6.2/ext/nokogiri/tmp/x86_64-redhat-linux-gnu/ports/libxml2/2.9.2/patch.log' to see what happened. *** extconf.rb failed *** Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options. |
The error message isn’t very helpful but the fix is fortunately easy. You install the nokogiri
Ruby Gem directly with the yum
utility. The following instructs yum
to proceed without waiting for you to type a y
to install.
yum install -y rubygem-nokogiri |
Loaded plugins: langpacks, refresh-packagekit Resolving Dependencies --> Running transaction check ---> Package rubygem-nokogiri.x86_64 0:1.6.6.2-1.fc20 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package Arch Version Repository Size ================================================================================ Installing: rubygem-nokogiri x86_64 1.6.6.2-1.fc20 updates 534 k Transaction Summary ================================================================================ Install 1 Package Total download size: 534 k Installed size: 834 k Downloading packages: rubygem-nokogiri-1.6.6.2-1.fc20.x86_64.rpm | 534 kB 00:00 Running transaction check Running transaction test Transaction test succeeded Running transaction (shutdown inhibited) Installing : rubygem-nokogiri-1.6.6.2-1.fc20.x86_64 1/1 Verifying : rubygem-nokogiri-1.6.6.2-1.fc20.x86_64 1/1 Installed: rubygem-nokogiri.x86_64 0:1.6.6.2-1.fc20 Complete! |
Now you can use the Ruby gem
utility to create the Rails framework like this:
gem install rails |
This will take a couple minutes typically, so be patient. You see something like this, dependent on the release:
Fetching: loofah-2.0.1.gem (100%) Successfully installed loofah-2.0.1 Fetching: rails-html-sanitizer-1.0.2.gem (100%) Successfully installed rails-html-sanitizer-1.0.2 Fetching: rails-deprecated_sanitizer-1.0.3.gem (100%) Successfully installed rails-deprecated_sanitizer-1.0.3 Fetching: rails-dom-testing-1.0.6.gem (100%) Successfully installed rails-dom-testing-1.0.6 Fetching: builder-3.2.2.gem (100%) Successfully installed builder-3.2.2 Fetching: erubis-2.7.0.gem (100%) Successfully installed erubis-2.7.0 Fetching: actionview-4.2.1.gem (100%) Successfully installed actionview-4.2.1 Fetching: actionpack-4.2.1.gem (100%) Successfully installed actionpack-4.2.1 Fetching: activemodel-4.2.1.gem (100%) Successfully installed activemodel-4.2.1 Fetching: arel-6.0.0.gem (100%) Successfully installed arel-6.0.0 Fetching: activerecord-4.2.1.gem (100%) Successfully installed activerecord-4.2.1 Fetching: globalid-0.3.5.gem (100%) Successfully installed globalid-0.3.5 Fetching: activejob-4.2.1.gem (100%) Successfully installed activejob-4.2.1 Fetching: mime-types-2.4.3.gem (100%) Successfully installed mime-types-2.4.3 Fetching: mail-2.6.3.gem (100%) Successfully installed mail-2.6.3 Fetching: actionmailer-4.2.1.gem (100%) Successfully installed actionmailer-4.2.1 Fetching: rake-10.4.2.gem (100%) Successfully installed rake-10.4.2 Fetching: thor-0.19.1.gem (100%) Successfully installed thor-0.19.1 Fetching: railties-4.2.1.gem (100%) Successfully installed railties-4.2.1 Fetching: bundler-1.9.2.gem (100%) Successfully installed bundler-1.9.2 Fetching: hike-1.2.3.gem (100%) Successfully installed hike-1.2.3 Fetching: multi_json-1.11.0.gem (100%) Successfully installed multi_json-1.11.0 Fetching: tilt-1.4.1.gem (100%) Successfully installed tilt-1.4.1 Fetching: sprockets-2.12.3.gem (100%) Successfully installed sprockets-2.12.3 Fetching: sprockets-rails-2.2.4.gem (100%) Successfully installed sprockets-rails-2.2.4 Fetching: rails-4.2.1.gem (100%) Successfully installed rails-4.2.1 Parsing documentation for actionmailer-4.2.1 Installing ri documentation for actionmailer-4.2.1 Parsing documentation for actionpack-4.2.1 Installing ri documentation for actionpack-4.2.1 Parsing documentation for actionview-4.2.1 Installing ri documentation for actionview-4.2.1 Parsing documentation for activejob-4.2.1 Installing ri documentation for activejob-4.2.1 Parsing documentation for activemodel-4.2.1 Installing ri documentation for activemodel-4.2.1 Parsing documentation for activerecord-4.2.1 Installing ri documentation for activerecord-4.2.1 Parsing documentation for arel-6.0.0 Installing ri documentation for arel-6.0.0 Parsing documentation for builder-3.2.2 Installing ri documentation for builder-3.2.2 Parsing documentation for bundler-1.9.2 Installing ri documentation for bundler-1.9.2 Parsing documentation for erubis-2.7.0 Installing ri documentation for erubis-2.7.0 Parsing documentation for globalid-0.3.5 Installing ri documentation for globalid-0.3.5 Parsing documentation for hike-1.2.3 Installing ri documentation for hike-1.2.3 Parsing documentation for loofah-2.0.1 Installing ri documentation for loofah-2.0.1 Parsing documentation for mail-2.6.3 Installing ri documentation for mail-2.6.3 Parsing documentation for mime-types-2.4.3 Installing ri documentation for mime-types-2.4.3 Parsing documentation for multi_json-1.11.0 Installing ri documentation for multi_json-1.11.0 Parsing documentation for rails-4.2.1 Installing ri documentation for rails-4.2.1 Parsing documentation for rails-deprecated_sanitizer-1.0.3 Installing ri documentation for rails-deprecated_sanitizer-1.0.3 Parsing documentation for rails-dom-testing-1.0.6 Installing ri documentation for rails-dom-testing-1.0.6 Parsing documentation for rails-html-sanitizer-1.0.2 Installing ri documentation for rails-html-sanitizer-1.0.2 Parsing documentation for railties-4.2.1 Installing ri documentation for railties-4.2.1 Parsing documentation for rake-10.4.2 Installing ri documentation for rake-10.4.2 Parsing documentation for sprockets-2.12.3 Installing ri documentation for sprockets-2.12.3 Parsing documentation for sprockets-rails-2.2.4 Installing ri documentation for sprockets-rails-2.2.4 Parsing documentation for thor-0.19.1 Installing ri documentation for thor-0.19.1 Parsing documentation for tilt-1.4.1 Installing ri documentation for tilt-1.4.1 Done installing documentation for actionmailer, actionpack, actionview, activejob, activemodel, activerecord, arel, builder, bundler, erubis, globalid, hike, loofah, mail, mime-types, multi_json, rails, rails-deprecated_sanitizer, rails-dom-testing, rails-html-sanitizer, railties, rake, sprockets, sprockets-rails, thor, tilt after 475 seconds 26 gems installed |
If you want to install Phusion Passenger, mod_passenger
is already installed. You should note that support and testing for this stops at Fedora V17. You can verify installation with the following command:
yum list mod_passenger |
It returns:
Loaded plugins: langpacks, refresh-packagekit
Available Packages
mod_passenger.x86_64 4.0.53-3.fc20.2 updates |
You can also install the Ruby Gem for Passenger, like this:
gem install passenger |
It should take less than 2 minutes and return something like this:
Fetching: passenger-5.0.6.gem (100%) Building native extensions. This could take a while... Successfully installed passenger-5.0.6 Parsing documentation for passenger-5.0.6 Installing ri documentation for passenger-5.0.6 Done installing documentation for passenger after 9 seconds 1 gem installed |
As always, I hope this was helpful. I’ll add a post with the remaining MySQL and Oracle connection details soon.